1、static作用(静态变量与函数,全局与局部的使用范围)
(1)函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,
因此其值在下次调用时仍维持上次的值;
(2)在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明
它的模块内;
(4)在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5)在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。
2、Object-C的内存管理?
(1)当你使用new,alloc和copy方法创建一个对象时,该对象的保留计数器值为1.需要手动向该对象发送一条release或autorelease消息,才能销毁对象。
(2)当你通过任何其他方法获得一个对象时,则假设该对象的保留计数器值为1,而且已经被设置为自动释放,不需要手动释放。如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它.
(3)如果你保留了某个对象,你需要(最终)释放或自动释放该对象,必须保持retain方法和release方法的使用次数相等.
3、为什么很多内置的类,如TableViewController的delegate的属性是assign不是retain?
循环引用,所有的引用计数系统,都存在循环应用的问题。
例如下面的引用关系:对象a创建并引用到了对象b,对象b创建并引用到了对象c,对象c创建并引用到了对象b.
这时候b和c的引用计数分别是2和1。当a不再使用b,调用release释放对b的所有权,因为c还引用了b,所以b的引用计数为1,b不会被释放。b不释放,c的引用计数就是1,c也不会被释放。从此,b和c永远留在内存中。这种情况,必须打断循环引用,通过其他规则来维护引用关系。
比如,我们常见的delegate往往是assign方式的属性而不是retain方式的属性,赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环引用。如果一个UITableViewController 对象a通 过retain获取了UITableView对象b的所有权,这个UITableView对象b的delegate(c)又是a,如果这个delegate是 retain方式的,那基本上就没有机会释放这两个对象了。自己在设计使用delegate模式时,也要注意这点。
4、定义属性时,什么情况使用copy、assign、retain?
assign用于简单数据类型,如NSInteger,double,bool,
retain和copy用于对象,copy相当于两个房间两把钥匙,retain相当于一个房间两把钥匙。
另外:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。
5、对象是什么时候被release的?
引用计数为0时。
autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的 Autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。
待深入理解runloop:
对于每一个Runloop,系统会隐式创建一个Autorelease pool,这样所有的release pool会构成一个象CallStack一样的一个栈式结构,在每一个 Runloop结束时,当前栈顶的Autorelease pool会被销毁,这样这个pool里的每个Object(就是autorelease的对 象)会被release。那什么是一个Runloop呢?一个UI事件,Timer call, delegate call, 都会是一个新的 Runloop。
6、tableView的重用机制?
查看UITableView头文件,会找到NSMutableArray* visibleCells和NSMutableDictnery* reusableTableCells(iOS 7 没有?)两个结构。visibleCells内保存当前可见的 cells,reusableTableCells保存可重用的cells。
TableView显示之初,reusableTableCells为空,那么 tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。开始的cell都是通过 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 来创建,而且cellForRowAtIndexPath只是调用最大显示cell数的次数。
比如:有100条数据,iPhone一屏最多显示10个cell。程序最开始显示TableView的情况是:
(1)用 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 创建10次cell,并给cell指定同样的重用标识(当然,可以为不同显示类型的cell指定不同的标识),并且10个cell全部都加入到 visibleCells数组,reusableTableCells为空。
(2)向下拖动tableView,当cell1完全移出屏幕,cell1移出visiableCells,cell1加入到reusableTableCells。
(3)接着向下拖动tableView,因为reusableTableCells中已经有值,所以,当需要显示新的 cell,cellForRowAtIndexPath再次被调用的时 候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。 cell1加入到visiableCells,cell1移出reusableTableCells;cell2移出 visiableCells,cell2加入到reusableTableCells。之后再需要显示的Cell就可以正常重用了。
9、类目的作用?与继承的区别
类目中方法的调用和原始类中的方法一样,类目中的方法也会被子类继承;
类目把一个很大的类分成多个小块来开发,更好维护;
类目就只能添加类方法,不能添加成员变量或者属性,继承就可以添加变量;
如果类目中写了一个跟原始类一样的方法,类目方法优先被访问;
类目的命名规则:类名+扩展方法。
10、怎么理解MVC,在Cocoa中MVC是怎么实现的?
Model: 代表你的应用程序是什么(不是怎么展现)
Controller: 控制你的Model怎么展现给用户(UI逻辑)
View: Controller的奴隶。。。
(1)Model,Controller,View相互通讯的规则:
Controller可以直接和Model通信
Controller也可以直接和View通信
Model和View永远不能直接通信
(2)iOS中View和Controller的通信是透明和固定的,主要通过outlet和action实现
View使用Delegate接口和Controller同步信息
View不直接和数据通信,使用dataSource接口从Controller处获取数据
View的delegate和dataSource一般就是Controller
Controller负责为View翻译和格式化Model的数据
Model使用Notification & KVO的方式分发数据更新信息,Controller可以有选择的监听自己感兴趣的信息。
View也可以监听广播信息,但一般不是Model发出的信息
一个完整的App就是很多MVC的集合
11、delegate和notification区别,分别在什么情况下使用?
Delegate:消息的发送者(sender)告知接收者(receiver)某个事件将要发生,delegate机制使得接收者可以改变发送者的行为。通常发送者和接收者的关系是直接的一对多的关系。
Notification:消息的发送者告知接收者事件已经发生或者将要发送,仅此而已,接收者并不能反过来影响发送者的行为。通常发送者和接收者的关系是间接的多对多关系。
(1)效率是delegate比nsnotification高, delegate方法比notification更加直接
(2)最典型的特征是,delegate方法往往需要关注返回值,也就是delegate方法的结果。比如-windowShouldClose:,需要关心返回的是yes还是no。所以delegate方法往往包含should这个很传神的词。 也就是好比你做我的delegate,我会问你我想关闭窗口你愿意吗?你需要给我一个答案,我根据你的答案来决定如何做下一步。相反的,notification最大的特色就是不关心接受者的态度,我只管把通告放出来,你接受不接受就是你的事情,同时我也不关心结果。所以 notification往往用did这个词汇,比如NSWindowDidResizeNotification,那么nswindow对象放出这个 notification后就什么都不管了也不会等待接受者的反应。
(3)两个模块之间联系不是很紧密,就用notification传值,例如多线程之间传值用notificaiton。
(4)delegate只是一种较为简单的回调,且主要用在一个模块中,例如底层功能完成了,需要把一些值传到上层去,就事先把上层的函数通过 delegate传到底层,然后在底层call这个delegate,它们都在一个模块中,完成一个功能。
12、属性变量与实例变量的差异
写在.h{}里的变量叫实例变量,这里面的变量默认是受保护的,子类可以访问,外界不能访问。
但是如果把实例变量声明为@public,外界就可以访问,但是与属性变量不同,属性变量通过.访问,实例变量通过->访问
.m文件里面的变量都是私有的,只有实例内部能访问。
13、当你为某个属性重写setter和getter中的其中一个方法,或者都没重写,编译器都会自动帮你添加上@synthesize语句。如果你在.m文件中同时重写了该属性的getter和setter方法,那么你就必须去手动去创建这个属性的实例变量,即手动加上@synthesize语句。
为什么关联到代码里的IBOutlet变量是weak类型。因为视图层已经强引用了该IBOutlet变量,所以控制器层就不需要再去强引用该变量。
instancetype这个类型会告诉编译器,这个方法返回的对象的类型和接受消息的对象类型一样。
当一个名为a的属性,声明在头文件中,并且为只读类型。但是,你在实现文件中想对a属性进行写操作。就可以在实现没见的类扩展中重新声明这个a属性,声明为readwrite。不过,一般情况下,readwrite是默认的。