美文网首页iOS学习
iOS objc_getAssociatedObject &am

iOS objc_getAssociatedObject &am

作者: LuKane | 来源:发表于2017-07-18 21:30 被阅读2340次

    一.AssociatedObject

    1.大家在iOS的学习和实战过程中往往会遇到一些相对来说深奥一点的语法.而今天在这里将会给大家叙述关于 AssociatedObject的基本运用:objc_getAssociatedObject && objc_setAssociatedObject

    2.说句实在话,我也是一个刚入行的小菜鸟,如果有写的不对的地方,请大家海涵和指点.(废话到此为止,直接上代码和注释)

    二. 导入头文件

    1. objc/runtime.h

    下面是一个数组, 和一个字符串

    NSArray *arr = [[NSArray alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
    NSString *overView = [NSString stringWithFormat:@"%@,%@",@"five",@"six"];
    
    

    调用方法1: 设置关联对象
    objc_setAssociatedObject(<#id object#>, <#const void *key#>, <#id value#>, <#objc_AssociationPolicy policy#>)

    • 1.第一个参数: id object : 需要传入的是 : 对象的主分支
    • 2.第二个参数: const void *key : 是一个 static 类型的 关键字,这里根据开发者自身来定义就行(尽量写的有根据一点,避免以后忘记是干啥用的)
    • 3.第三个参数: id value : 传入的是: 对象的子分支
    • 4.第四个参数: objc_AssociationPolicy policy :是当前关联对象的类型 strong,weak,copy (枚举类型:开发者可以点进去看)

    类的主分支:如果将一个label控件和控制器关联上,而且放在控制器上面,那么这个控制器对象 self 或者 self.view 就充当 主分支

    子分支 : 那么这个label 就充当 子分支

    ③如果 控制器上有两个控件, 一个Label, 一个 View, 那么想这两个控件 弄上关联关系, 这两个控件随意一个做主分支,一个做子分支(这个根据开发场景而定)

    2.如何确定主分支和子分支

    如果子分支内存被释放了, 主分支没有释放, 那么可以通过 objc_getAssociatedObject获取到 子分支(虽然它被释放了,但是一样可以获取到) . 如果主分支被释放了,子分支没有释放, 则获取不到任何一个对象

    调用方法2: 获取关联对象
    objc_getAssociatedObject(<#id object#>, <#const void *key#>)就相对来说容易理解一点了

    • 1.第一个参数 : 主分支
    • 2.第二个参数 : 关键字

    三.代码和注释

    下面有讲到 解除关联对象, 以及 删除关联对象 objc_removeAssociatedObjects

    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSArray *arr = [[NSArray alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
        NSString *overView = [NSString stringWithFormat:@"%@,%@",@"five",@"six"];
    
        // 设置关联对象
        objc_setAssociatedObject(arr, &overViewKey, overView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        
        //  NSLog(@"%@==%@",arr,overView); // 正常打印结果 ,如果arr 没有被释放,就算overView被释放了, 也可以用到 overView.因为它们两关联起来了
        
        // 上面已经将 arr 和 overView 关联上了, 在这里 通过 objc_getAssociatedObject :arr , 和关键字 overViewKey ,将关联对象获取出来
        NSString *associatedObj = objc_getAssociatedObject(arr, &overViewKey);
        NSLog(@"associatedObj:%@",associatedObj); // 打印结果: associatedObj:five,six
        
        // 释放 关联对象
        // 第三个参数, 设为 nil, 则将 arr 与 nil 关联... 也等同于 : 没关联任何对象
        objc_setAssociatedObject(arr, &overView, nil, OBJC_ASSOCIATION_ASSIGN);
        
        // 移除 所有关联对象 : 这个方法 相当于 初始化 arr 对象一样(并不是初始化arr这个指针所指向的内存地址)
        objc_removeAssociatedObjects(arr);
    }
    

    四.看到别人代码块里头会用到 _cmd 这个关键字

    此关键字代表的是什么?

    - (UILabel *)textLabel{
        return objc_getAssociatedObject(self, _cmd);
    }
    

    上面代码 直接通过 objc_getAssociatedObject方法获取到 textLabel 关联的关键字, 或者 对象本身 或者 Bool 等等
    而关键在于下面一个句代码:

    - (void)setTextLabel:(UILabel *)textLabel{
        objc_setAssociatedObject(self, @selector(textLabel), textLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    

    _cmd :第一句返回的时候,相当于返回一个 id对象 ,而关键字则是 : textLabel ,它是根据当前方法,直接使用方法的名称,即 - (***)textLabel 方法,并且能保证改名称不重复.(第一句代码方法名 : textLabel ,因为一个类中不可能用相同的方法名)

    第二句代码中出现 @selector(textLabel),这里它就调用第一句代码了, @selector直接返回SEL,则获取到textLabel的方法名,则为第一句代码返回的值.

    // 1.直接口述代码吧. 
    // 2.上面两个方法 写在一个 单独的View中,在这个类的 .h中,创建一个 weak(若引用)的textLabel,而在.m文件中 initWithFrame中直接创建self.textLabel = [[UILabel alloc] initWithFrame:self.bounds];并添加到这个view上
    // 3.那么按照常理来说, 这里应该报警告, 但是 在控制器中打印 这个类的 textLabel , 你会发现是有内存的, 如果把第一句和第二句代码注释掉, 打印则没有内存.
    
    

    如果有什么疑问或者写的不对的地方,希望大家能帮忙指出来.谢谢

    相关文章

      网友评论

        本文标题:iOS objc_getAssociatedObject &am

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