OC语言特性

2021-06-22  本文已影响0人  叔简

分类

用分类做了哪些事情

特点

分类中都可以添加哪些内容?

分类的调用栈(Category)

分类_objc_init调用栈.png

如果两个分类添加同一个函数名称的函数,哪一个函数最终生效?

取决于编译顺序,最后生成分类的函数会生效,前面的将被覆盖掉。

总结:

能否给分类添加”成员变量”?

不能在分类的声明和定义实现的时候直接为分类添加成员变量,但是可以通过关联对象的技术来为分类添加”成员变量”,来达到分类可以添加”成员变量的效果”。
关联对象的3个API:

objc_setAssociatedObject(<#id  _Nonnull object#>, <#const void * _Nonnull key#>, <#id  _Nullable value#>, <#objc_AssociationPolicy policy#>)
objc_getAssociatedObject(<#id  _Nonnull object#>, <#const void * _Nonnull key#>)
objc_removeAssociatedObjects(<#id  _Nonnull object#>)

① 设定一个value值,通过key值建立一个映射关系,然后通过policy策略,关联到object上
② 根据指定的key到object中获取关联的值
③ 根据对象,移除所有相关它的对象

我们用关联对象技术来实现为分类添加”成员变量”,这个成员变量会被添加到哪里?

① 我们为分类所添加的成员变量肯定不是在宿主类中的。
② 关联对象由AssociationsManager管理并在AssociationHashMap存储。
③ 我们创建的每一个对象的关联对象实际上都存储在了AssociationHashMap这样的容器中。
④ 所有对象的关联内容都在同一个全局容器中
⑤ 不同对象的关联对象的值都会放到全局容器中
⑥ 假如想消除一个关联对象时,可以传入value为nil操作来实现

关联对象

关联对象本质

关联对象由AssociationsManager管理并在AssociationHashMap存储。
我们创建的每一个对象的关联对象实际上都存储在了AssociationHashMap这样的容器中。
所有对象的关联内容都在同一个全局容器中

利用关联对象添加成员变量

1. - (void)setName:(NSString *)name { objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
2. - (NSString *)name
{
    // 隐式参数
    // _cmd == @selector(name)
    return objc_getAssociatedObject(self, _cmd);
}
(void)removeAssociatedObjects{
    // 移除所有关联对象
    objc_removeAssociatedObjects(self);
}
关联对象的本质.png 关联对象的Json形式.png

扩展

类扩展一般都在宿主类的.m文件中。

一般用扩展做什么?

特点

  1. 分类是运行时决议、扩展是编译时决议
  2. 分类可以有声明和实现,而扩展只有声明的形式,实现是直接在宿主类的
  3. 可以为系统类添加分类,但是不能为系统类添加扩展

代理

代理的工作流程

三个角色:

代理方和委托方以什么关系存在?

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


代理循环引用.png

通知实现机制

如何实现通知的机制?假如说自己实现这种机制如何实现?

通知传递消息一对多的流程

通知一对多的流程.png

通知和代理的区别

KVO

什么是KVO?

KVO的实现机制

KVOisa混写.png

重写setter方法

通过KVC设置value能够生效?

通过成员变量直接赋值value能否生效

观测方法的options

总结

KVC

什么是KVC?

使用KVC是否会违背于面向对象的编程思想

KVC的key是没有限制的,如果我们知道这个对象内部的私有变量名称的话,我们可以在外界修改、访问它,从这个角度来考虑的话是会破坏面向对象的思想的

valueForKey的实现流程

KVCGetter方法的流程.png

Accessor Method方法的定义

setValue:forKey的实现流程

KVCsetter方法的流程.png

Accessor Method方法的定义

instance var

属性关键字

属性关键字分为哪几类

assign的特点

weak 特点

assign和weak的区别有哪些?

1、weak只可以修饰对象、而assign可以修饰基本数据类型和对象
2、assign修饰的对象的时候,当对象被释放掉以后,assign指针还是会指向对象的地址,而weak修饰的对象,在对象释放后,weak的指针会被置nil

copy

源对象类型 拷贝方式 目标对象类型 拷贝类型
mutable对象 copy 不可变 深拷贝
mutable对象 mutableCopy 可变 深拷贝
immutable对象 copy 不可变 浅拷贝
immutable对象 mutableCopy 可变 深拷贝

① 可变对象的copy和mutablecopy都是深拷贝
② 不可变对象的copy是浅拷贝,mutablecopy是深拷贝
③ copy方法返回的都是不可变对象

浅拷贝

深拷贝

深拷贝VS浅拷贝?

@property(copy) NSMutableArray *array, 会产生什么样的问题

最终结果是一个不可变的对象,那么你在修改这个数组的时候会崩溃

MST

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

@property(nonatomic,retain)id obj;

- (void)setObj:(id)obj{
    //对象不等判断
    //如果传递过来的obj对象是原来的obj对象
    //实际上也是在传递过来的obj对象release的操作,有可能会直接释放掉了传递过来的对象,
    //这时候如果还去访问被释放的对象就会崩溃
    if(_obj != obj){
        [_obj release];
        _obj = [obj retain]
    }
}

2、 分类的实现原理

3、KVO实现原理是怎么样的?

4、能否为分类添加实例变量?

@interface CustomView (dd)

- (NSString *)name;
- (void)setName:(NSString *)name;

@end

.m

@implementation CustomView (dd)

/*
 * 使用关联对象模拟实例变量
 * 使用objc_getAssociatedObject、objc_setAssociatedObject模拟『属性』的存取方法
 */

- (NSString *)name{
    
    return objc_getAssociatedObject(self, _cmd);
    
}

- (void)setName:(NSString *)name{
    
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
}
@end
上一篇下一篇

猜你喜欢

热点阅读