Dynamic language
OC is a dynamic language, and its method, the type of object, is to be determined only when it is run. So this makes OC a powerful mechanism for associating objects.
Associating objects
The so-called associative object, in fact, is that we bind an object to an existing object at run time, and make two objects into a dynamic aggregation relationship.
The associated object and property have the same keyword, and the following is the storage policy for the associated object:
retain
Association type |
equivalent @property property |
objc_association_assign |
assign |
objc_association_retain_nonatomic |
nonatomic,retain |
objc_association_copy_nonatomic |
nonatomic,copy |
objc_association_retain |
objc_ Association_copy |
copy |
The associated object is mainly based on the following three functions, all at <objc/runtime>
void Objc_setassociatedobject (ID object, void *key, id value, Objc_associationpolicy policy)
Setting Association objects
Parameters |
Description |
Object |
The object to be associated with |
Key |
A memory representation that when comparing two associative objects is equal, the larger is the memory address, so it is generally represented by a global static variable |
Value |
The object being associated with |
Policy |
Storage policies |
ID objc_getassociatedobject (ID object, void *key)
Get Association Object
void Objc_removeassociatedobjects (ID object)
Delete an associated object
Role
Association objects are typically used to dynamically extend an object, but this is usually used when other methods do not work, because the associated object is likely to have a bug that is difficult to find.
The association object is sometimes used to add attributes to the class in the category, which is later analyzed.
The following demo dynamically binds a block above the Uialertview and integrates the button handling logic with the alert call.
static char *AlertKey = "alertKey";
- (void)viewDidLoad {
[super viewDidLoad];
alert = [[UIAlertView alloc] initWithTitle:@"alert" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"other", nil];
alert.delegate = self;
}
- (IBAction)click:(id)sender {
void (^block) (NSInteger) = ^(NSInteger buttonIndex){
if (buttonIndex == 0){
NSLog(@"click cancel");
}
else{
NSLog(@"click other");
}
};
objc_setAssociatedObject(alert, AlertKey, block, OBJC_ASSOCIATION_COPY);
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
void (^block)(NSInteger) = objc_getAssociatedObject(alertView, AlertKey);
block(buttonIndex);
}
Run the program by clicking on two buttons to output the following separately
2015-08-11 22:51:27.146 Dynamic[4592:2833778] click other
2015-08-11 22:51:28.262 Dynamic[4592:2833778] click cancel
Next we'll add a addition property to Uiviewcontroller in the category
#import "ViewController.h"
#import <objc/runtime.h>
@interface UIViewController (Addition)
@property(nonatomic ,copy) NSString *addition;
@end
#import "UIViewController+Addition.h"
static const void *IndieBandNameKey = &IndieBandNameKey;
@implementation UIViewController (Addition)
-(void)setAddition:(NSString *)addition{
objc_setAssociatedObject(self, IndieBandNameKey, addition, OBJC_ASSOCIATION_COPY);
}
-(NSString *)addition{
return objc_getAssociatedObject(self, IndieBandNameKey);
}
@end
Here, the correlation is actually the formal parameter addition, and the property has nothing to do with, write @property is to be able to use '. ' Grammar. However, it is not easy to misunderstand that the attribute store policy in @porperty is consistent with the associated object.
So every time setaddition actually we do not modify the original memory value, but change the pointer point to the address, here need to pay attention to.
Then modify the code for the alert just now
- (void)viewDidLoad {
[super viewDidLoad];
alert = [[UIAlertView alloc] initWithTitle:@"alert" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"other", nil];
alert.delegate = self;
self.addition = @"addition";
}
- (IBAction)click:(id)sender {
void (^block) (NSInteger) = ^(NSInteger buttonIndex){
if (buttonIndex == 0){
NSLog(@"click cancel");
objc_removeAssociatedObjects(self);
}
else{
NSLog(@"click other");
NSLog(@"%@",self.addition);
}
};
objc_setAssociatedObject(alert, AlertKey, block, OBJC_ASSOCIATION_COPY);
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
void (^block)(NSInteger) = objc_getAssociatedObject(alertView, AlertKey);
block(buttonIndex);
}
Note three bold statements, and then we run to see the results
2015-08-11 22:53:54.353 Dynamic[4655:2849502] click other
2015-08-11 22:53:54.353 Dynamic[4655:2849502] addition
2015-08-11 22:53:55.804 Dynamic[4655:2849502] click cancel
2015-08-11 22:53:57.491 Dynamic[4655:2849502] click other
2015-08-11 22:53:57.491 Dynamic[4655:2849502] (null)
First we used the associated object, so when we clicked on other we would see the print out of the addition. Click Cancel again because we remove the association object, and then click on the other when the addition becomes null.
objective-c--associated Objects