OC基础

作者: 一只长毛猫 | 来源:发表于2018-04-28 18:53 被阅读4次

    内容要点

    分类
    扩展
    关联对象
    代理
    通知
    KVC
    属性关键字

    分类

    分类可以做什么?

    1 实例方法
    2 类方法
    3 协议
    4 属性
    作用是:声明私有方法,分解庞大的类文件

    分类的结构如下:
    struct category_t {
        const char *name;
        classref_t cls;
        struct method_list_t *instanceMethods;
        struct method_list_t *classMethods;
        struct protocol_list_t *protocols;
        struct property_list_t *instanceProperties;
        ……
    }
    
    分类特点

    1 运行时决议:编译时没有添加,运行时才通过Runtime添加
    2 最后编译的类,最先添加到数组中。方法查找时,根据选择器名称查找,最优先查找头部方法。
    第一步:依次编译分类A、B、C
    第二步:运行时,有个二维数组,倒序添加编译过的分类(CBA)
    第三步:在宿主方法列表的index=0的位置,插入二维数组中的内容


    结论

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

    扩展Extension

    扩展可以做什么?

    1 声明私有属性
    2 声明私有方法(仅方便阅读)
    3 声明私有成员变量

    扩展和分类区别

    1 分类是运行时决议,扩展是编译时决议
    2 分类可以有声明有实现,扩展只有声明,实现写在宿主的.m中
    3 可以给系统类添加分类,不能给系统类添加扩展
    运行时决议:编译期并没有把分类方法添加到宿主类中,而是在运行时才添加。

    关联对象

    关键方法

    能否为分类添加成员变量? 可以,使用关联对象

    id objc_getAssociatedObject(id object, const void *key)
    void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    void objc_removeAssociatedObjects(id object)
    
    关联对象的本质

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


    代理Delegate

    代理是一种软件设计模式,iOS中以@protocol形式实现,传递方式一对一


    通知Notification

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

    通知本质是:一个Map,以notificationName为key找到注册的对象列表,然后遍历对象,一次调用通知方法。

    KVO

    1 KVO是 观察设计者模式的实现
    2 Apple使用了isa 混写(isa - swizzling)来实现KVO
    生效条件
    1 使用setter方法改变值KVO才会生效
    2 使用setValue: forKey: 改变值KVO会生效
    3 成员变量直接修改需手动添加KVO才会生效(willChangeValueForKey didChangeValueForKey)

    isa混写就是指改变isa的指向。假设Person对象person添加了KVO观察后,会在运行时生成一个Person的子类NSKVONotifying_Person, 那么person的isa是指向Person类的,此时会被重写,改为指NSKVONotifying_Person类。NSKVONotifying_Person类修改了setter方法。


    KVC

    键值编码技术 在 NSObject(NSKeyValueCoding)中定义

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

    无论调用setValue还是valueForKey,key必须是类定义的。否则会抛异常.
    由于可以通过这种方式改变私有变量,所以会破坏面向对象编程思想。

    setValue调用顺序

    setter方法,变量,如果还是没有setValue:forUndefinedKey:抛异常

    valueForKey调用顺序

    getter方法,变量,valueForUndefinedKey抛异常

    属性关键字

    读写权限

    readonly readwrite. default is readwrite

    原子性

    atomic(赋值,获取线程安全) nonatomic . default is atomic.
    atomic修饰的数组,数组赋值与获取保证线程安全。但是数组添加,移除不负责线程安全。

    引用计数

    retain/strong
    assign/unsafe_unretained (基本,对象)/MRC
    weak
    copy

    assign和weak区别 ?

    assign 会产生悬垂指针
    不改变被修饰对象的引用计数
    修饰基本数据类型,如int BOOL等
    weak
    不改变被修饰对象的引用计数
    所修饰的对象被释放之后会自动置为nil

    copy关键字

    copy后的都是不可变的
    mutableCopy的都是可变的
    只有不可变对象的 copy是浅拷贝,其他都是深拷贝


    总结

    @property(copy)NSMutableArray *array?

    可能会造成程序崩溃
    原因是:array不管是NSMutableArray还是NSArray经过copy后,都是NSArray。
    NSMutableArray经过copy是深拷贝,产了NSArray不可变对象
    NSArray经过copy是浅拷贝,产生了NSArray指针。
    但是由于array被声明为NSMutableArray所以,可能会调用addObject这些方法,导致崩溃。

    MRC重写retain修饰变量的setter方法?

    if(_obj != obj){
    [_obj release];
    _obj = [obj retain];
    }

    分类实现原理?

    运行时决议,不同分类同名方法,最后参与编译的最终生效。

    KVO实现原理?

    观察着模式实现,运用了isa混写技术,动态添加子类。让isa指向子类。

    相关文章

      网友评论

        本文标题:OC基础

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