美文网首页iOS 进阶文集
Objective-C相关常见问题

Objective-C相关常见问题

作者: 繁华落尽丶lee | 来源:发表于2018-08-06 19:48 被阅读1次

一、分类

分类都做了什么?

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

分类的特点

  • 运行时决议,编好分类后并没有直接添加到宿主类中,而是在运行时通过Runtime添加到宿主类中。
  • 可以为系统类添加分类。

分类可以添加哪些内容

  • 实例方法
  • 类方法
  • 协议
  • 属性,只是添加了setter和getter方法。
    Runtime中有源码。

多个分类中有同名方法,哪个方法会生效?

最后编译的分类中的方法会生效。倒序遍历,所以最先添加的那个生效。

分类中的方法会“覆盖”宿主类的方法的原因

因为分类中的方法会插入到宿主方法列表数组的前边,先查找到返回。

分类的机制或者原理

  • 分类添加的方法可以“覆盖”原类方法
  • 同名分类方法谁生效取决于编译顺序
  • 名字相同的分类会引起编译报错

能否为分类添加实例变量

可以通过关联对象实现

消化这篇文章Category不再是问题 深入理解Objective-C:Category -- 美团技术团队

二、关联对象

什么是关联对象

id objc_getAssociatedObject(id object, const void * key) // 通过key在Object获取关联的
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
void objc_removeAssoicatedObjects(id object)

成员变量被添加到哪里了?

关联对象有AssociationsManager管理并在AssociationHashMap存储,
所有对象的关联内容都在同一个全局容器中。

AssociationsHashMap --> ObjectAssociationMap --> ObjectAssociation

关联对象的本质.png

参考文章关联对象 AssociatedObject 完全解析

三、扩展

做什么?

  • 声明私有属性
  • 声明私有方法
  • 声明私有成员变量

与分类的区别

  • 编译时决议
  • 只以声明的形式存在,多数情况下在宿主类的.m中
  • 不能为系统类添加扩展

四、代理

什么代理

  • 一种软件设计模式
  • iOS当中以@protocol形式体现
  • 传递方式一对一

工作流程

代理流程.png

问题

  • 一般声明为weak以规避循环引用。代理方strong委托方,委托方weak代理方。

五、通知

特点

  • 使用观察者模式实现的用于跨层传递消息的机制
  • 传递方式一对多

实现机制和原理是怎样的

发送者 ---> 通知中心 ---> 多个接收者

怎样实现通知机制?

Notification_Map ---> NotificationObject

六、KVO

什么是KVO?

  • KVO是OC对观察者模式的一种实现
  • Apple使用isa混写(isa-swizzling)来实现KVO。

实现机制

KVO实现原理.png

系统在运行时,动态创建了一个子类NSKVONotifying_A类,重写Setter方法。

重写的Setter添加的方法

    • (void)willChangeValueForKey:(NSString *)key;
    • (void)didChangeValueForKey:(NSString *)key;
// NSKVONotifying_A 的Setter实现
- (void)setValue:(id)obj {
    [self willChangeValueForKey: @"keyPath"];
    // 调用父类实现,也即原类的实现
    [super setValue:obj];
    [self didChangeValueForKey: @"keyPath"];
}

KVC会触发KVO吗?

会,setValue:forKey:会调用,KVO重写的Setter方法。

通过成员变量直接赋值是否能触发KVO?

不会,需要调用willChangeValueForKey:didChangeValueForKey:,这是手动KVO的实现。

总结

  • 使用Setter方法改变值KVO能生效
  • 使用setValue:forKey:改变值KVO能生效
  • 成员变量直接修改需要手动添加KVO才会生效

七、KVC

什么是KVC?

KVC是Key Value coding的缩写,键值编码技术。

    • (id)valueForKey:(NSString *)key
    • (Void)setValue:(id)value forKey:(NSString *)key

八、属性关键字

属性关键字的分类

  • 读写权限
  • 原子性
  • 引用计数

读写权限

  • readonly
  • readWrite(默认)

原子性

  • atomic (默认)
  • nonatomic

引用计数

  • retain/strong
  • assign/unsafe_unretained
  • weak
  • copy

assign和weak的区别

assign

  • assign可以修改基本数据类型
  • 修改对象类型,不改变引用计数
  • 释放后,还会指向原地址,会产生悬垂指针

weak

  • 不改变被修改对象的引用计数
  • 所指对象在释放之后自动置为nil

copy

@propery (copy) NSMutableArray *array; 

问题:

浅拷贝和深拷贝

  • 浅拷贝,复制内存地址,增加引用计数,没有发生新的内存分配。
  • 深拷贝,新开辟内存,复制内容。不会增加引用计数,开辟新的内存空间。

区别?

  • 是否开辟新的内存空间?
  • 是否影响引用计数?

copy关键字使用

  • 可变对象 --> copy操作后 ==> 生成不可变对象 ==> 深拷贝
  • 可变对象 --> mutableCopy ==> 可变 ==> 深拷贝
  • 不可变对象 --> copy ==> 不可变 ==> 浅拷贝
  • 不可变对象 --> mutableCopy ==> 可变 ==> 深拷贝

总结

  • 对于可变对象的copy和mutableCopy都是深拷贝
  • 不可变对象的Copy是浅拷贝,mutableCopy是深拷贝
  • copy方法返回不可变对象

相关文章

网友评论

    本文标题:Objective-C相关常见问题

    本文链接:https://www.haomeiwen.com/subject/pkjivftx.html