Before you begin, it is recommended that you read the basics of iOS Runtime: iOS Essentials: Runtime
There is a package in the interview, encountered such a question: "How to add a property to Nsarray (cannot use inheritance)", the package immediately forced, can not use inheritance, is it classified? But the classification can only add a method can not add properties Ah, the package is not the solution, until later came into contact with the runtime before it dawned.
What is an association object
An association object refers to an OC object that is connected to an instance of a class by a unique key.
For example: Xiaoming is an instance of the person class, and his dog (a OC object) is led by him through a string (key), which can be said that Xiaoming and dog are connected, of course xiaoming can lead multiple dog.
How to associate an object
The runtime provides us with the method:
//关联对象void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)//获取关联的对象id objc_getAssociatedObject(id object, const void *key)//移除关联的对象void objc_removeAssociatedObjects(id object)
Variable Description:
id object:被关联的对象(如xiaoming)const void *key:关联的key,要求唯一id value:关联的对象(如dog)objc_AssociationPolicy policy:内存管理的策略
The enum values for Objc_associationpolicy policy are:
OBJC_ASSOCIATION_ASSIGN = 0, OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, OBJC_ASSOCIATION_COPY_NONATOMIC = 3, OBJC_ASSOCIATION_RETAIN = 01401, OBJC_ASSOCIATION_COPY = 01403
When the object is disposed, it is determined whether the associated object is disposed or not, and when the policy is retain/copy, the associated object is released (release), and when it is assign, it will not be freed.
It is important to note that we do not need to invoke removeassociated actively to contact the associated object, and if we need to deallocate the specified object, we can use Setassociatedobject to set nil.
Application of associated objects
1. Add Public properties
This is the most commonly used pattern, usually we will add attributes in the class declaration, but for some requirements (as described in the preface), we need to add one or more attributes in the classification, the compiler will error, the solution to this problem is to use the runtime's association object.
Application Examples:
We need to customize a tabbar and expose public properties and methods. (Readers can think of the advantages and disadvantages of using inheritance and classification implementations)
@interface UITabBarController (Custom)@property (nonatomic, strong) SUCustomTabbar * customTabbar;@end
#import "UITabBarController+Custom.h"#import <objc/runtime.h>@implementation UITabBarController (Custom)- (void)setCustomTabbar:(UIView *)customTabbar { //这里使用方法的指针地址作为唯一的key objc_setAssociatedObject(self, @selector(customTabbar), customTabbar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}- (UIView *)customTabbar { return objc_getAssociatedObject(self, @selector(customTabbar));}//其他方法...@end
In this way, we can use the custom tabbar like the native Tabbar:
[self.tabBarController.customTabbar doSomgthig];
2. Add a Private member variable
Sometimes, you need to add member variables in the taxonomy that you don't want to expose to public declarations.
Application Example: A callback to add a click time to a button
@interface UIButton (Callback)-(Instancetype) initWithFrame: (CGRect) frame Callback: (void (^) (UIButton *)) Callbackblock; @end
@interface UIButton ()@property (nonatomic, copy) void (^callbackBlock)(UIButton * button);@end@implementation UIButton (Callback)- (void (^)(UIButton *))callbackBlock { return objc_getAssociatedObject(self, @selector(callbackBlock));}- (void)setCallbackBlock:(void (^)(UIButton *))callbackBlock { objc_setAssociatedObject(self, @selector(callbackBlock), callbackBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);}- (instancetype)initWithFrame:(CGRect)frame callback:(void (^)(UIButton *))callbackBlock { if (self = [super initWithFrame:frame]) { self.callbackBlock = callbackBlock; [self addTarget:self action:@selector(didClickAction:) forControlEvents:UIControlEventTouchUpInside]; } return self;}- (void)didClickAction:(UIButton *)button { self.callbackBlock(button);}@end
Readers think: Is there a memory management problem with the above code?
3. Associated KVO Observer
Sometimes we use KVO in classification, we recommend using the associated object as the observer, and try to avoid the object observing itself.
This application pattern is no longer an example, and interested readers can delve into it themselves or paste the code into a comment.
Thinking
1. More application patterns for related objects?
2. Is the associated object the first choice to solve the problem?
3. Side effects of associated objects?
You are welcome to exchange discussions.
Transferred from: http://www.jianshu.com/p/c68cc81ef763
IOS Runtime app: associating objects