iOS面试题(二)--Object-C语言特性相关

107 阅读4分钟

1.分类Category相关

1.1你用分类做了哪些事?

声明私有方法、 分解体积庞大的类文件 把Framework的私有方法公开

1.2分类的特点? 运行时决议 可以为系统类添加分类

1.3分类中都可以添加哪些内容? 实例方法 类方法 协议 属性(只添加了get和set方法,而不是添加了实例变量)

1.4两个分类中的同名方法,哪个方法生效?

最后编译的分类中的方法会最终生效。 也就是说分类方法会“覆盖”宿主类的方法。

另:名字相同的分类会引起编译报错。

2.关联对象相关

2.1能否为分类添加“成员变量”? 我们不能在分类的声明或者定义实现的时候直接为分类添加成员变量,但是可以通过关联对象的技术来为分类添加实例变量。

id objc_getAssociatedObject(id object,const void *key)

void objc_setAssociatedObject(id object,const void *key,id value, object_AssociationPolicy policy)

void objc_removeAssociatedObjects(id object)

2.2通过关联对象添加的实例变量被添加到哪了呢? 关联对象由AssociationsManager管理并在AssociationsHashMap存储,所有对象的关联内容都被放到一个统一的全局容器中。

2.3关联对象的本质

image.png

image.png

2.4怎么擦除某一个关联对象被关联的值? 可以通过objc_setAssociatedObject方法的值传成nil

3.扩展相关

3.1一般用扩展做什么 ? 声明私有属性 声明私有方法 声明私有成员变量

3.2扩展的特点,或者分类和扩展的区别? 扩展是编译时决议,分类是运行时决议。 扩展只以声明的形式存在,多数情况下寄生于宿主类的.m中,分类可以有声明,有实现。 扩展不能为系统类添加扩展,分类可以为系统类添加分类。

4.代理相关

4.1什么事代理? 准确的是一种软件设计模式,iOS中以@protocol形式体现,传递方式一对一。

4.2代理的工作流程? 委托方要求代理方需要实现的接口都定义在协议当中,在协议当中可以声明属性、方法。代理方按照协议实现方法。代理方可能返回一个处理结果给委托方。委托方可以调用代理方遵从的协议方法。

image.png

4.3在实际使用代理模式中,委托方和代理方的关系应该如何建立?应该注意哪些问题?

一般声明为weak以规避循环引用。

5.通知相关

5.1通知和代理的区别? 通知是使用观察者模式来实现的用于跨层传递消息的机制。代理是代理模式 通知的传递方式为一对多。代理是一对一。

5.2如何实现通知机制? 通知中心NSNotificationCenter会维护一个Map表,或者说字典,key是notificationName,value是ObserverList。

image.png

6.KVO相关

6.1什么是KVO? KVO是Object-C对观察者设计模式的又一实现。 系统使用了isa混写(isa-swizzling)来实现KVO。

6.2isa混写技术在KVO中是怎样体现的? 当我们调用了addObserver:ForKeyPath:后,系统会在运行时动态创建NSKVONotifing_A类,同时将原来的类A的isa指针指向新创建的类。

image.png

6.3通过KVC设置value能否生效? 可以生效

6.4通过成员变量直接赋值value能否触发KVO?怎么手动触发KVO?

不能触发KVO, 在对成员变量赋值时候,在其前后分别添加

[self willChangeValueForKey:@"value"]

[self didChangeValueForKey:@"value"]

就可以实现手动KVO,didChangeValueForKey在系统内部实现当中会触发KVO回调。

7.KVC相关

-(id)valueForKey:(NSString *)key

-(void)setValue:(id)value forKey:(NSString *)key

7.1通过KVC是否会破坏面向对象的编程方法? 会。

7.2valueForKey调用流程

image.png

7.3setValue:forKey调用流程

image.png

8.属性关键字相关

读写权限 readonly readwrite(默认) 原子性 atomic(默认) nonatomic 引用计数 retain/stron assign weak copy

8.1atomic 修饰的数组,能保证线程安全吗? 对数组添加、移除对象时,无法保证,只对赋值和获取保证安全的。

8.2assign和weak的区别? assign和weak都不改变被修饰对象的引用计数。 assign修饰基本数据类型,如int,BooL等,weak可以修饰对象和基本数据类型。 assign所指对象在被释放后仍让指向该内存地址,weak所指对象在被释放后会自动置nil。

8.3@property(copy)NSMutableArray *array会导致什么问题? 如果赋值过来的是NSMutableArray,copy之后是NSArray, 如果赋值过来的是NSArray,copy之后是NSArray, 由于原来的属性被声明为MutableArray,那么调用方进行添加和移除对象的方法时,因为copy结果是不可变的NSArray,则会造成crash异常。

8.4 深拷贝和浅拷贝的区别? 是否开辟了新的内存空间 是否影响了引用计数

8.5copy 可变对象的copy和mutableCopy都是深拷贝, 不可变对象的copy是浅拷贝,mutableCopy是深拷贝。 copy方法返回的都是不可变对象 image.png

8.6MRC下如何重写retain修饰变量的setter方法?

@property (nonatomic, retain) id obj;

-(void)setObj:(id)obj{ if(_obj != obj){ [_obj release]; _obj = [obj retain]; } }