ObjcAssociatedObjectHelpers 2.0.1

ObjcAssociatedObjectHelpers 2.0.1

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布上次发布2015年7月

Jonathan Crooke 维护。



  • Jonathan Crooke

简介

关联对象(或关联引用)是在 OS X 10.6 和 iOS 4.0 中引入的。这个特性给类实例提供了一个字典,可以在其中使用运行时函数 objc_setAssociatedObject()objc_getAssociatedObject() 存储任意对象。本项目旨在让它们的使用更加方便,并以轻量级和彻底测试的方式实现。

  1. 为类别添加 ivars - 由于 Obj-C 分类不允许添加或合成 ivars,即使可以添加属性,这是一个不幸的缺点。关联对象可以用来提供存储,以克服这一限制

    @interface NSObject (MyCategory)
    @property (strong) id myCategoryObject;
    @end
    
    @implementation NSObject (MyCategory)
    SYNTHESIZE_ASC_OBJ(myCategoryObject, setMyCategoryObject);
    @end
    
  2. NSObject 的任意字典 - NSObject 分类向 NSObject 添加了一个延迟初始化的 NSMutableDictionary,允许将键值对方便地关联到任何 NSObject 子类实例

    [self.associatedDictionary setValue:@"value" forKey:@"myKey"];
    

备注

  1. 获取器/设置器名称 - 在预处理程序中无法操作字符串,因此不能从单个标记轻松生成标准获取器和设置器名称。因此,需要手动提供两个名称。
  2. 内存管理 - 在 ARC 和手动引用计数代码下均工作相同。
  3. 属性内存管理语义 - 由于属性使用关联对象进行存储,因此可以使用任何属性设置器语义

    @property () id myProperty;     
    @property (strong) id myProperty;
    @property (retain) id myProperty;
    @property (assign) id myProperty;
    @property (copy) id myProperty;
    

    目前,宏在运行时检查对 NSCopying 协议的合规性,如果在找到的情况下使用 OBJC_ASSOCIATION_COPY,否则使用 OBJC_ASSOCIATION_RETAIN。测试 -[UnitTests testMutableObject] 确认已复制。我认为这是正确的方式。然而,最好还是使用这些设置器中的正常语义。

  4. 自版本 2.0.0 开始支持弱属性,其行为与常规 weak 属性相同。

使用

提供的静态库用于 NSObject 分类,或仅使用头文件进行基本使用。建议使用 CocoaPods 进行安装。

pod 'ObjcAssociatedObjectHelpers'

测试

提供了详尽的测试用例,覆盖率近 100%。

  1. SYNTHESIZE_ASC_OBJ(getterName, setterName) - 最基本的使用方法。为读写对象属性合成 getter 和 setter。如果你希望生成一个只有私有或保护 setter 的只读属性,可以在其他分类中定义。

    @interface MyClass : NSObject
    @property (readonly) id readWriteObject;
    @end
    
    @interface MyClass (PrivateOrProtectedOrAnonymous)
    @property (readwrite) id readWriteObject;
    @end
    
    @implementaton MyClass
    
    - (id) init {
        if ((self = [super init])) {
            self.readWriteObject = @"foo";
        }
        return self;
    }
    
  2. SYNTHESIZE_ASC_PRIMITIVE(getterName, setterName, type) - 为任何类型的原始对象合成。支持任何由 @encode() 运算符支持的类型。所以应该...一切都是支持的?

  3. SYNTHESIZE_ASC_OBJ_LAZY(getterName, class) - 合成一个在首次访问时通过懒加载进行初始化的只读对象。必须提供对象类以便在首次访问时可以初始化(通过 alloc/init)对象。
  4. SYNTHESIZE_ASC_OBJ_LAZY_EXP(getterName, initExpression) - 合成一个在首次访问时懒加载进行初始化的只读对象,并提供一个初始化表达式。例如:

    SYNTHESIZE_ASC_OBJ_LAZY_EXP(nonDefaultLazyObject, [NSString stringWithFormat:@"foo"])    
    

    使用表达式 [NSString stringWithFormat:@"foo"] 初始化对象。请注意 SYNTHESIZE_ASC_OBJ_LAZY 使用这个宏与 [[class alloc] init]

  5. 所有宏都有带有 _BLOCK 后缀的伴随宏,它(借用通用编程语法)接受一个类型为 T(^block)(T value) 的块,用于 getter 和 setter(如果可用)。这允许在访问器中运行额外的代码,类似于覆盖访问器。传递给访问器的值将是参数。这个值可以被返回,也可以返回一个修改后的值。这取代了直到 v1.2.1 所使用的语法,我认为这更清晰。例如

    SYNTHESIZE_ASC_PRIMITIVE_BLOCK(myProperty,
                                   setMyProperty,
                                   CGSize,
                                   ^(CGSize s){ return CGSizeZero; },
                                   ^(CGSize s){ s.width = 10; return s; })
    

    定义一个类型为 CGSize 的读写属性,并覆盖 getter 和 setter 以始终设置为 CGSizeZero,并始终返回一个宽度为 10 的大小。

如果你喜欢这个,你可能还会喜欢...

更新内容

v2.0.1

  • 在 podspec 中将 ARC 设置为必需,因为这是使用 Cocoapods 中 weak 功能所必需的。

v2.0.0

  • 块访问宏的新格式。值直接传递并必须返回。这是一个破坏性变更。
  • weak 属性添加了一个新功能,使用这里提供的包装方法在这里建议的方法。
  • NSObject 分类现在有前缀并分解为一个子规范以用于 Cocoapods。

v1.2.1

  • ARC 不再是必需(它从未真正是必需的)。
  • 进行了一些春季清洁。

v1.2.0

  • 现在为所有宏发送 KVO 通知。对此前版本有疏忽。

v1.1.2

  • 改进了块宏值处理。请见下文详情。

v1.1.1

  • 移动了 setter 块的执行顺序,以便在将新值设置之前块可以执行潜在的操作。在块的作用域中,self.property 将是现有值, 新值被设置之前。

v1.1

  • 将块传递给宏以修改设置值或获取返回值,以及执行其他自定义代码。

v1.0

  • 为 iOS 提供静态库目标,为 OS X 提供框架目标。
  • MIT 许可证

享受乐趣!

MIT 许可协议 >> [email protected]