美文网首页
Runtime之category关联属性

Runtime之category关联属性

作者: AYuan_ | 来源:发表于2016-03-26 22:41 被阅读583次

    类扩展时Apple又只提供了对方法的扩展,对属性的扩展是不会自动生成_变量以及属性的setter:和getter方法。但苹果提供了runtime,我们可以通过runtime使用关联API就可以做到对属性的扩展。

    /** 
     * Sets an associated value for a given object using a given key and association policy.
     * 
     * @param object The source object for the association.
     * @param key The key for the association.
     * @param value The value to associate with the key key for object. Pass nil to clear an existing association.
     * @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
     */
    void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
     
    /** 
     * Returns the value associated with a given object for a given key.
     * 
     * @param object The source object for the association.
     * @param key The key for the association.
     * 
     * @return The value associated with the key \e key for \e object.
     */
    id objc_getAssociatedObject(id object, const void *key)
     
    /** 
     * Removes all associations for a given object.
     * 
     * @param object An object that maintains associated objects.
     * 
     * @note The main purpose of this function is to make it easy to return an object 
     *  to a "pristine state”. You should not use this function for general removal of
     *  associations from objects, since it also removes associations that other clients
     *  may have added to the object. Typically you should use \c objc_setAssociatedObject 
     *  with a nil value to clear an association.
     */
    void objc_removeAssociatedObjects(id object)
     
    
    • 设置关联值

    对于设置关联,我们需要使用下面的API关联起来:

    /**
    object:与谁关联,通常是传self
    key:唯一键,在获取值时通过该键获取,通常是使用static const void *来声明
    value:关联所设置的值
    policy:内存管理策略,比如使用copy
    
    */
    void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    
    • 获取关联值

    如果我们要获取所关联的值,需要通过key来获取,调用如下函数:

    /**
    object:与谁关联,通常是传self,在设置关联时所指定的与哪个对象关联的那个对象
    key:唯一键,在设置关联时所指定的键
    */
    id objc_getAssociatedObject(id object, const void *key)
    
    • 关联策略

    我们先看看设置关联时所指定的policy,它是一个枚举类型,看官方说明:

    /**
     * Policies related to associative references.
     * These are options to objc_setAssociatedObject()
     */
    typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
        OBJC_ASSOCIATION_ASSIGN = 0,           /**< Specifies a weak reference to the associated object. */
        OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. 
                                                *   The association is not made atomically. */
        OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**< Specifies that the associated object is copied. 
                                                *   The association is not made atomically. */
        OBJC_ASSOCIATION_RETAIN = 01401,       /**< Specifies a strong reference to the associated object.
                                                *   The association is made atomically. */
        OBJC_ASSOCIATION_COPY = 01403          /**< Specifies that the associated object is copied.
                                                *   The association is made atomically. */
    };
    

    关联类型与等效@property属性
    OBJC_ASSOCIATION_ASSIGN:assign(弱引用关联,通常是基本数据类型,如int、float)
    OBJC_ASSOCIATION_RETAIN_NONATOMIC:nonatomic,retain(表示强(strong)引用关联对象)
    OBJC_ASSOCIATION_COPY_NONATOMIC:nonatomic,copy(表示关联对象copy)
    OBJC_ASSOCIATION_RETAIN:retain(表示强(strong)引用关联对象,但不是线程安全的)
    OBJC_ASSOCIATION_COPY:copy(表示关联对象copy,但不是线程安全的)

    例子

    UIViewController + viewInfo.h文件

    #import <UIKit/UIKit.h>
    @interface UIViewController (viewInfo)
    @property (nonatomic, copy) NSString *name; //视图名字
    @property (nonatomic, assign) BOOL hasChildViewController; //是否有子视图
    @property (nonatomic, strong) UIImage *backgroundImage; //背景图片
    @end
    

    UIViewController + viewInfo.m文件

    #import "UIViewController+viewInfo.h"
    #import <objc/runtime.h>
    static const void *kName = "name";
    static const void *kHasChildViewController = @"hasChildViewController";
    static const void *kBackgroundImage = @"backgroundImage";
    @implementation UIViewController (Information)
    #pragma mark - 字符串类型的动态绑定
    - (NSString *)name {
         return objc_getAssociatedObject(self, kName);
    }
    - (void)setName:(NSString *)name {         
         objc_setAssociatedObject(self, kName, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    #pragma mark - BOOL类型的动态绑定
    - (BOOL)hasChildViewController { 
         return [objc_getAssociatedObject(self, kHasChildViewController) boolValue]; 
    }
    - (void)setHasChildViewController:(BOOL)hasChildViewController { 
         objc_setAssociatedObject(self, kHasChildViewController, [NSNumber numberWithBool:hasChildViewController], OBJC_ASSOCIATION_ASSIGN);
    }
    #pragma mark - 类类型的动态绑定
    - (UIImage *)backgroundImage { 
         return objc_getAssociatedObject(self, kBackgroundImage);
    }
    - (void)setBackgroundImage:(UIImage *)backgroundImage {    
        objc_setAssociatedObject(self, kBackgroundImage, backgroundImage, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    @end
    

    相关文章

      网友评论

          本文标题:Runtime之category关联属性

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