面试题
2016-06-22 11:54
387 查看
转载:https://segmentfault.com/a/1190000004196352
1.iOS怎么管理内存?
在ObjC中对象时存储在堆中的,系统并不会自动释放堆中的内存(注意基本类型 是由系统自己管理的,放在栈上)。如果一个对象创建并使用后没有得到及时释 放那么就会占用大量内存。OjbC中的内存管理就需要由开发人员手动维护。 1)引用计数器:在ObjC中每个对象内部都有一个与之对应的整数(retainCount),叫“引用计数器”,当一个对象在创建之后它的引用计数器为1, 当调用这个对象的alloc、retain、new、copy方法之后引用计数器自动在原 来的基础上加1(ObjC中调用一个对象的方法就是给这个对象发送一个消息), 当调用这个对象的release方法之后它的引用计数器减1,如果一个对象的引用 计数器为0,则系统会自动调用这个对象的dealloc方法来销毁这个对象。 2)属性参数:可以通过@property定义属性,此刻不必手动实现 getter,setter方法程序仍然没有内存泄露,因为属性定义的时候我们同样加 上了参数
3)自动释放池:一种内存自动释放的机制叫做“自动引用计数”(或“自动释放 池”),使用@autoreleasepool关键字声明一个代码块,如果一个对象在初始 化时调用了autorelase方法,那么当代码块执行完之后,在块中调用过 autorelease方法的对象都会自动调用一次release方法。这样对象就起到了 延迟自动释放的效果. 注意: ######1.autorelease方法不会改变对象的引用计数器,只是将这个对象放 到自动释放池中; ######2.自动释放池实质是当自动释放池销毁后调用对象的release方法,不 一定就能销毁对象(例如如果一个对象的引用计数器>1则此时就无法销毁); ######3.由于自动释放池最后统一销毁对象,因此如果一个操作比较占用内存 (对象比较多或者对象占用资源比较多),最好不要放到自动释放池或者考虑放 到多个自动释放池; ######4.ObjC中类库中的静态方法一般都不需要手动释放,内部已经调用了 autorelease方法;
2.浅复制和深复制的区别
浅复制:本质是将一个对象1的地址,交给了另一个对象2,如果对象被释放,则对 象2所指的地址是不安全的. 深复制:要使用copy方法,则对象必须遵守NSCopying协议 实质:将原对象的内容复制到一块新的内存空间,拷贝的是整个对象.
3.类别和类扩展的区别?
1)类扩展仅能够在原始类中声明(.h或.m中均可,在.m中声明的类扩展其定义的 属性和方法均是私有的) 2)类扩展的实现仅能够在原始类的.m中编写 3)在类扩展中可以扩展类的属性.而在分类中仅能够扩展实例方法和类方法
4.使用block和使用delegate完成委托模式有什么优点?
1)使用block实现委托模式优点回调的block代码块定义在委托对象函数内部,使代码更为紧凑;适配对象不再 需要实现具体某个protocol,代码更为简洁。代码可读性更强,更有连贯性, block经常可以用于completion handler、error handler等。网络请求回调。
2)delegate的优势:
1.非常严格的语法。所有将听到的事件必须是在delegate协议中有清晰的定义。 2.如果delegate中的一个方法没有实现那么就会出现编译警告/错误 3.协议必须在controller的作用域范围内定义 4.在一个应用中的控制流程是可跟踪的并且是可识别的; 5.在一个控制器中可以定义多个不同的协议,每个协议有不同的delegate 6.没有第三方对象要求保持/监视通信过程。 7.能够接收调用的协议方法的返回值。这意味着delegate能够提供反馈信息给controller
5.#import和#include的区别 @class?
@class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文 件中还是需要使用#import 而#import比起#include的好处就是不会引起交叉编译
6.在一个对象的方法里面:self.name = "object";和name = "object"有什么不同吗?
self.name ="object":会调用对象的setName()方法; name = "object":会直接把object赋值给当前对象的name属性。
7.请简要说明viewDidLoad和viewDidUnload何时调用
viewDidLoad在view从nib文件初始化时调用, loadView在controller的view为nil时调用。 此方法在编程实现view时调用,view控制器默认会注册memory warning notification, 当view controller的任何view没有用的时候, viewDidUnload会被调用,在这里实现将retain的view release,如果是 retain的IBOutlet view 属性则不要在这里release,IBOutlet会负责 release 。
8.数组和指针的区别
(1)数组可以申请在栈区和数据区;指针可以指向任意类型的内存块 (2)sizeof作用于数组时,得到的是数组所占的内存大小;作用于指针时,得 到的都是4个字节的大小 (3)数组名表示数组首地址,值不可以改变,如不可以将++作用于数组名上; 普通指针的值可以改变,如可将++作用于指针上 (4)用字符串初始化字符数组是将字符串的内容拷贝到字符数组中;用字符串初 始化字符指针是将字符串的首地址赋给指针,也就是指针指向了该数组
9.static的作用
(1)函数体内static 变量的作用范围为该函数体,不同于 auto 变量,该变 量的内存只被分配一次, 因此其值在下次调用时仍维持上次的值; (2)在模块内的static 全局变量可以被模块内所用函数访问,但不能被模块外 其它函数访问; (3)在模块内的static 函数只可被这一模块内的其它函数调用,这个函数的使 用范围被限制在声明 它的模块内; (4)在类中的static 成员变量属于整个类所拥有,对类的所有对象只有一份拷 贝; (5)在类中的static 成员函数属于整个类所拥有,这个函数不接收 this 指 针,因而只能访问类的static 成员变量。
10.简述内存分区情况
(1)代码区:存放函数二进制代码 (2)数据区:系统运行时申请内存并初始化,系统退出时由系统释放。存放全局变 量、静态变量、常量 (3)堆区:通过malloc等函数或new等操作符动态申请得到,需程序员手动申请和释 放 (4)栈区:函数模块内申请,函数结束时由系统自动释放。存放局部变量、函数参数
11.const char p; charconstp; charconst p; const char const p;四个修饰指针有什么区别
(1)定义了一个指向不可变的字符串的字符指针 (2)和(1)一样 (3)定义了一个指向字符串的指针,该指针 c5d5 值不可改变,即不可改变指向 (4)定义了一个指向不可变的字符串的字符指针,且该指针也不可改变指向
12.MVC的理解?
MVC模式考虑三种对象:模型对象、视图对象和控制器对象。 模型对象负责应用程序的数据和定义操作数据的逻辑; 视图对象知道如何显示应用程序的模型数据; 控制器对象是M与V之间的协调者。
13.obj-c的优缺点
objc优点: 1) Cateogies 2) Posing 3) 动态识别 4) 指标计算 5)弹性讯息传递 6) 不是一个过度复杂的 C 衍生语言 7) Objective-C 与 C++ 可混合编程 缺点: 1) 不支援命名空间 2) 不支持运算符重载 3) 不支持多重继承 4) 使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优 化方法都用不到。(如内联函数等),性能低劣。
14.队列和栈有什么区别:
队列和栈是两种不同的数据容器。从"数据结构"的角度看,它们都是线性结构, 即数据元素之间的关系相同。 队列是一种先进先出的数据结构,它在两端进行操作,一端进行入队列操作,一 端进行出列队操作。 栈是一种先进后出的数据结构,它只能在栈顶进行操作,入栈和出栈都在栈顶操 作。
15.简述视图控件器的生命周期。
loadView尽管不直接调用该方法,如多手动创建自己的视图,那么应该覆盖这个 方法并将它们赋值给试图控制器的view属性。 viewDidLoad只有在视图控制器将其视图载入到内存之后才调用该方法,这是执 行任何其他初始化操作的入口。 viewDidUnload当试图控制器从内存释放自己的方法的时候调用,用于清楚那些 可能已经在试图控制器中创建的对象。 viewVillAppear当试图将要添加到窗口中并且还不可见的时候或者上层视图移 出图层后本视图变成顶级视图时调用该方法,用于执行诸如改变视图方向等的操 作。实现该方法时确保调用[super viewWillAppear:]. viewDidAppear当视图添加到窗口中以后或者上层视图移出图层后本视图变成顶 级视图时调用,用于放置那些需要在视图显示后执行的代码。确保调用[super viewDidAppear:]。
16.UIView与CLayer有什么区别?
1) UIView是iOS系统中界面元素的基础,所有的界面元素都是继承自它。它本 身完全是由CoreAnimation来实现的。它真正的绘图部分,是由一个CALayer 类来管理。UIView本身更像是一个CALayer的管理器,访问它的跟绘图和跟坐标 有关的属性。 2) UIView有个重要属性layer,可以返回它的主CALayer实例。 3) UIView的CALayer类似UIView的子View树形结构,也可以向它的layer上 添加子layer,来完成某些特殊的表示。即CALayer层是可以嵌套的。 4) UIView的layer树形在系统内部,被维护着三份copy。分别是逻辑树,这里 是代码可以操纵的;动画树,是一个中间层,系统就在这一层上更改属性,进行 各种渲染操作;显示树,其内容就是当前正被显示在屏幕上得内容。 5) 动画的运作:对UIView的subLayer(非主Layer)属性进行更改,系统将 自动进行动画生成,动画持续时间的缺省值似乎是0.5秒。 6) 坐标系统:CALayer的坐标系统比UIView多了一个anchorPoint属性,使 用CGPoint结构表示,值域是0~1,是个比例值。这个点是各种图形变换的坐标 原点,同时会更改layer的position的位置,它的缺省值是{0.5,0.5},即在 layer的中央。 7)渲染:当更新层,改变不能立即显示在屏幕上。当所有的层都准备好时,可以 调用setNeedsDisplay方法来重绘显示。 8)变换:要在一个层中添加一个3D或仿射变换,可以分别设置层的transform或 affineTransform属性。 9)变形:Quartz Core的渲染能力,使二维图像可以被自由操纵,就好像是三维 的。图像可以在一个三维坐标系中以任意角度被旋转,缩放和倾斜。 CATransform3D的一套方法提供了一些魔术般的变换效果。
17.线程与进程的区别和联系?
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元 实现系统对应用的并发性。 程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地 址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是 一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单 独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线 程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要 求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
18.ios平台怎么做数据的持久化?coredata和sqlite有无必然联系?coredata是一个关系型数据库吗?
iOS中可以有四种持久化数据的方式:属性列表、对象归档、SQLite3和Core Data;core data可以使你以图形界面的方式快速的定义app的数据模型,同时在你的代码中 容易获取到它。coredata提供了基础结构去处理常用的功能,例如保存,恢复, 撤销和重做,允许你在app中继续创建新的任务。在使用core data的时候,你不用安装额外的数据库系统,因为core data使用内置的 sqlite数据库。core data将你app的模型层放入到一组定义在内存中的数据对 象。coredata会追踪这些对象的改变,同时可以根据需要做相反的改变,例如用 户执行撤销命令。当core data在对你app数据的改变进行保存的时候,core data会把这些数据归档,并 永久性保存。 mac os x中sqlite库,它是一个轻量级功能强大的关系数据引擎,也很容易嵌 入到应用程序。可以在多个平台使用,sqlite是一个轻量级的嵌入式sql数据库 编程。与core data框架不同的是,sqlite是使用程序式的,sql的主要的API来直接操作数据 表。 Core Data不是一个关系型数据库,也不是关系型数据库管理系统(RDBMS)。虽 然Core Dta支持SQLite作为一种存储类型,但它不能使用任意的SQLite数据 库。Core Data在使用的过程种自己创建这个数据库。Core Data支持对一、对多的关系。
19.tableView的重用机制?
UITableView通过重用单元格来达到节省内存的目的:通过为每个单元格指定一 个重用标识符(reuseIdentifier),即指定了单元格的种类,以及当单元格滚出 屏幕时,允许恢复单元格以便重用.对于不同种类的单元格使用不同的ID,对于简 单的表格,一个标识符就够了.
20.用变量a给出下面的定义
a) 一个整型b) 一个指向整型数的指针
c) 一个指向指针的的指针,它指向的指针是指向一个整型数
d) 一个有10个整型数的数组
e) 一个有10个指针的数组,该指针是指向一个整型数的
f) 一个指向有10个整型数数组的指针
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数
a) int a; b) int *a; c) int **a; d) int a[10] e) int *a[10]; f) int (*a)[10]; g) int (*a)(int); i) int (*a[10])(int);
相关文章推荐
- java面试题及答案
- 面试题(1)
- 程序员如何挽救一个失败的项目?
- 程序员技术练级攻略
- Android 面试题
- 程序员:混日子不是你的错,根源在这里
- 前端简单面试题
- Story share IBM 一同事职业发展履历
- LayoutInflater——80%的Android程序员对它并不了解甚至错误使用
- 程序员修炼之道阅读笔记02
- android面试日记--20160619
- 面试感想
- 程序员文件名的规范
- 每个程序员都应该收藏的算法复杂度速查表
- 黑马程序员前端培训:用好课程打造高薪学员
- 做技术到底是应该俗还是雅
- 腾讯的面试题,据说很多人答不上来!
- C面试宝典——概念题
- 前端面试题网站集
- HashTable和HashMap的区别