• iOS关联对象


    Associated Objects(关联对象)或者叫作关联引用(Associative References),是作为Objective-C 2.0 运行时功能被引入到 Mac OS X 10.6 Snow Leopard(及iOS4)系统。与它相关在<objc/runtime.h>中有3个C函数,它们可以让对象在运行时关联任何值:

    OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
    OBJC_EXPORT void objc_removeAssociatedObjects(id object)

    为什么这几个方法很有用呢?因为开发者可以通过它们在分类中给已存在的类中添加自定义属性

    key 值

    关于前两个函数中的 key 值是我们需要重点关注的一个点,这个 key 值必须保证是一个对象级别(为什么是对象级别?看完下面的章节你就会明白了)的唯一常量。一般来说,有以下三种推荐的 key 值:

    1. 声明 static char kAssociatedObjectKey; ,使用 &kAssociatedObjectKey 作为 key 值;
    2. 声明 static void *kAssociatedObjectKey = &kAssociatedObjectKey; ,使用 kAssociatedObjectKey 作为 key 值;
    3. 用 selector ,使用 getter 方法的名称作为 key 值。

    我个人最喜欢的(没有之一)是第 3 种方式,因为它省掉了一个变量名,非常优雅地解决了计算科学中的两大世界难题之一(命名)。

    关联策略

    在给一个对象添加关联对象时有五种关联策略可供选择:

    /**
             *  OBJC_ASSOCIATION_ASSIGN  
                等价于@property (assign) ,
                     @property (unsafe_unretained)
                弱引用关联对象
             
             *  OBJC_ASSOCIATION_RETAIN_NONATOMIC
                等价于@property (strong, nonatomic)
                强引用关联对象,且为非原子操作
             
             *  OBJC_ASSOCIATION_COPY_NONATOMIC
                等价于@property (copy, nonatomic)
                复制关联对象,且为非原子操作
             
             
             *  OBJC_ASSOCIATION_RETAIN
                等价于@property (strong, atomic)
                强引用关联对象,且为原子操作
             
             *  OBJC_ASSOCIATION_COPY
                等价于@property (copy, atomic)
                复制关联对象,且为原子操作
             
             其中,第 2 种与第 4 种、第 3 种与第 5 种关联策略的唯一差别就在于操作是否具有原子性。
             */
            objc_setAssociatedObject(button, buttonKey, _imgView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    例子:

    1、倒入头文件,声明key:

    #import <objc/runtime.h>
    char* const buttonKey = "buttonKey";

    2、设置关联:

    if (groupModel.isOpened) {
            UIImageView * _imgView = [[UIImageView alloc]initWithFrame:CGRectMake(10, (44-16)/2, 14, 16)];
            [_imgView setImage:[UIImage imageNamed:@"ico_list"]];
            [sectionView addSubview:_imgView];
            CGAffineTransform currentTransform = _imgView.transform;
            CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform, M_PI/2); // 在现在的基础上旋转指定角度
            _imgView.transform = newTransform;
            objc_setAssociatedObject(button, buttonKey, _imgView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }else{
            UIImageView * _imgView = [[UIImageView alloc]initWithFrame:CGRectMake(10, (44-16)/2, 14, 16)];
            [_imgView setImage:[UIImage imageNamed:@"ico_list"]];
            [sectionView addSubview:_imgView];
            objc_setAssociatedObject(button, buttonKey, _imgView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
      

    3、获取关联:

    - (void)buttonPress:(UIButton *)sender//headButton点击
    {
        GroupModel *groupModel = dataSource[sender.tag];
        UIImageView *imageView =  objc_getAssociatedObject(sender,buttonKey);
    
        if (groupModel.isOpened) {
                [UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionTransitionNone animations:^{
                    CGAffineTransform currentTransform = imageView.transform;
                    CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform, -M_PI/2); // 在现在的基础上旋转指定角度
                    imageView.transform = newTransform;
    
    
                } completion:^(BOOL finished) {
                    
    
                }];
            
            
            
        }else{
            
                [UIView animateWithDuration:0.3 delay:0.0 options: UIViewAnimationOptionAllowUserInteraction |UIViewAnimationOptionCurveLinear animations:^{
    
                    CGAffineTransform currentTransform = imageView.transform;
                    CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform, M_PI/2); // 在现在的基础上旋转指定角度
                    imageView.transform = newTransform;
                
                } completion:^(BOOL finished) {
                    
                }];
            }
    
        groupModel.isOpened = !groupModel.isOpened;
    
        [expandTable reloadSections:[NSIndexSet indexSetWithIndex:sender.tag] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
  • 相关阅读:
    Effective C++ 学习一
    JavaScript 定义类和继承类的基本步骤
    Vararg collection Factory Method
    apache之httpd启动、终止、重启小结
    Thinking in C++ 学习笔记[1]
    Creational Pattern 之 Abstract Factory
    Perl WEB 开发之 Template
    C语言博客作业数据类型
    C语言博客作业一二维数组
    C语言博客作业函数
  • 原文地址:https://www.cnblogs.com/HOYF/p/5658627.html
Copyright © 2020-2023  润新知