1.请简述你对协议的理解?
protocol无论在哪个领域都是一种约束、规范。在OC中的协议主要用于在各个类之间进行回调传值。协议有委托方、代理方。委托方是协议的制定者,需要声明协议的方法,实现协议的对象。代理方,是协议的遵守者,需要遵守协议,并实现协议中的方法。
2.如何理解ARC自动引用计数机制?
Cocoa采用了引用计数(reference counting)机制,每一个对象有一个关联的“整数retainCount”用于记录对象的使用情况。对象被引用时,retainCount+1,外部环境结束对象的使用后retainCount-1。当retainCount为0的时候,该对象被销毁。
当我们使用alloc、new或者copy的时候需要销毁这个对象。release方法,只是将对象的retainCount值减1,并不是删除对象。当retainCount==0的时候,系统会发给对象一个dealloc消息,另外:千万不要手动调用dealloc,因为我们不知道何时、何地、何人还会使用该对像。应该老老实实依赖引用计数机制完成内存管理。
释放对象所有权的函数出了release还有autorelease,这是一种延迟操作。
3.如何理解retain、copy、assign、release、autorelease、dealloc关键字?
copy:建立一个索引计数为1的对象,然后释放旧对象,主要用于NSString
retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
assign:简单赋值,不更改索引计数
release:手动释放对象
dealloc:它的作用是,当对象的引用计数为0,系统会自动调用dealloc方法,回收内存。
autorelease原理:(1)先建立一个autorelease pool;(2)autorelease pool里面生成;(3)对象生成之后调用autorelease函数,这个函数的作用仅仅是在autorelease pool中做个标记,让pool记得将来release一下这个对象;(4)程序结束时,pool本身也需要release,此时pool会把每一个标记为autorelease的对象release一次。如果某个对象此时retain count大于1,这个对象还是没有被销毁。
4.self.name与_name的区别
self.name是通过方法进行引用的,包含了set和get方法。而通过下划线是获取自己的实例变量,不包含set和get的方法。
self.name是对属性的访问,而_name是对局部变量的访问。所有被声明为属性的成员,在iOS5之前需要使用编译指令@synthesize来告诉编译器帮助生成属性的getter和setter方法,之后,这个指令可以不用人为的指定了,默认情况下编译器会帮助我们生成。编译器在生成getter,setter方法是是有优先级的,它首先查找当前的类中用户是否定义属性的getter、setter方法,如果有,则编译器会跳过,不会再生成,使用用户定义的方法。也就是说你在使用self.name时是调用一个getter方法,会使引用计数加1,而_name不会使引用计数加1
所以使用self.name是更好的选择,因为这样可以兼容懒加载,同时也避免了使用下滑线的时候忽略了self这个指针,后者容易在Block中造成循环引用。同时,使用 '_' 是获取不到父类的属性,因为它只是对局部变量的访问。(即点语法实际上是getter和setter方法的间接调用,下划线方法是直接对变量操作。
5.继承与类别的联系与区别
联系:
可以给一个类扩展新的方法,或修改已有的方法
区别:
(1)继承修改的方法不会对父类原方法产生影响;类别修改的方法相当于替换了原有方法
(2)以ViewController举例,继承一个ViewController相当于建立一个新的页面,而给一个ViewController添加类别用于增加或者修改原ViewController上的方法。
(3)类别支持开发人员针对自己构建的类,把相关的方法分组到多个单独的文件中,对于大型而复杂的类,这有助于提高可维护性,并简化单个源文件的管理。
(4)针对系统提供的一些类,例如:NSString、NSArray、NSNumber等类,系统本身不提倡使用继承去扩展方法,因为这些类的内部实现对继承有所限制,所以最后使用类别来进行方法扩展。
(5)理论上类别不能新增属性
6.strong与weak的区别
weak和strong的不同是:当一个对象不再有strong类型的指针指向它的时候,它会被释放,即使还要weak型指针指向它。一旦最后一个strong型指针离去,这个对象将被释放,所有剩余的weak型指针都将被清除。
7.私有API与公开API的区别
iPhone中的API出了公开的API:Published API之外(或者叫文档记录的API:Documented API),还有两类API:私有API(Private)和未公开的API(UNPublished API或者叫文档中未记录的API:UNDocumented api)。其中私有API是指放在PrivateFrameworks框架中的API,未公开的API是指虽然放在frameworks框架中,但是却没有在苹果的官方文档中有使用说明、代码介绍等记录的API。后两种API是有区别的,按苹果的说法,未公开的API是还不够成熟,可能还会变动的API,等完全成型后会变成公开的API,但是目前不对其提供承诺,就是系统版本升级后可能会失效。而私有API是苹果明确不能使用的API。虽然两者有所区别,但是在具体使用方法上是类似的。
8.#import "xxx.h"和@class+类名的区别
(1)import会包含这个类的所有信息,包括实体变量和方法,而@class只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,暂时不用考虑,后面会再告诉你。
(2)在头文件中,一般只需要知道被引用的类的名称就可以了。不需要世道其内部的实体变量和方法,所以在头文件中一般使用@class来声明这个名称是类的名称。而在实现类里面,因为会用到这个引用类的内部的实体变量和方法,所以需要使用#import来包含这个被引用类的头文件。
(3)在编译效率方面考虑,如果你有100个头文件都#import了同一个头文件,或者这些文件是一次引用的,如A->B,B->C,C->D这样的引用关系。当最开始的那个头文件有变化的话,后面所有引用它的类都需要重新编译,如果你的类有很多,这将耗费大量的时间,而用@class则不会。
(4)如果有循环依赖关系,如A->B,B->A这样的相互依赖关系,如果使用#import来相互包含,那么就会出现编译错误,如果使用@class在两个类的头文件中相互声明,则不会有编译错误出现。
所以一般来说,@class是放在interface中的,只是为了在interface中引用这个类,把这个类作为一个类型来用的。在实现这个接口的实现类中,如果需要引用这个类的实体变量或者方法之类的,还是需要#import那个在@class中声明的类
网友评论