What is objc_setAssociatedObject() and in what cases should it be used?

后端 未结 4 1163
有刺的猬
有刺的猬 2020-11-28 20:26

In a project I have taken on, the original author has opted to use objc_setAssociatedObject() and I\'m not 100% clear what it does or why they decided to use it

4条回答
  •  悲哀的现实
    2020-11-28 21:06

    Here is a list of use cases for object associations:

    one: To add instance variables to categories. In general this technique is advised against, but here is an example of a legitimate use. Let's say you want to simulate additional instance variables for objects you cannot modify (we are talking about modifying the object itself, ie without subclassing). Let's say setting a title on a UIImage.

    // UIImage-Title.h:
    @interface UIImage(Title)
    @property(nonatomic, copy) NSString *title;
    @end 
    
    // UIImage-Title.m:
    #import 
    #import 
    
    static char titleKey;
    
    @implementation UIImage(Title)
    - (NSString *)title
    {
        return objc_getAssociatedObject(self, &titleKey);
    }
    
    - (void)setTitle:(NSString *)title
    {
        objc_setAssociatedObject(self, &titleKey, title, OBJC_ASSOCIATION_COPY);
    }
    @end
    

    Also, here is a pretty complex (but awesome) way of using associated objects with categories.. it basically allows you to pass in a block instead of a selector to a UIControl.


    two: Dynamically adding state information to an object not covered by its instance variables in conjunction with KVO.

    The idea is that your object gains state information only during runtime (ie dynamically). So the idea is that although you can store this state info in an instance variable, the fact that you're attaching this info into a an object instantiated at runtime and dynamically associating it with the other object, you are highlighting the fact that this is a dynamic state of the object.

    One excellent example that illustrates this is this library, in which associative objects are used with KVO notifications. Here is an excerpt of the code (note: this KVO notification isn't necessary to run make the code in that library work.. rather it's put there by the author for convenience, basically any object that registers to this will be notified via KVO that changes have happened to it):

    static char BOOLRevealing;
    
    - (BOOL)isRevealing
    {
        return [(NSNumber*)objc_getAssociatedObject(self, &BOOLRevealing) boolValue];
    } 
    
    - (void)_setRevealing:(BOOL)revealing
    {
        [self willChangeValueForKey:@"isRevealing"];
        objc_setAssociatedObject(self, &BOOLRevealing, 
           [NSNumber numberWithBool:revealing], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        [self didChangeValueForKey:@"isRevealing"];
    }
    

    bonus: take a look at this discussion/explanation of associated objects by Mattt Thompson, author of the seminal AFNetworking library

提交回复
热议问题