objc_setAssociatedObject、objc_getAssociatedObject、objc_removeAssociatedObjects

来源:互联网 发布:淘宝怎样申请退换货 编辑:程序博客网 时间:2024/05/17 07:48

一 关联的3个方法

  • objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
/** *  关联你需要关联的对象 * *  @param object   调用我的类,常见的是self *  @param key      一个关联的key值。有点类似,字典的key和广播的Name *  @param value    关联的对象  特别:设置成nil,则表示删除该对象的某一个扩展属性 *  @param policy   关联的方式  OBJC_ASSOCIATION_RETAIN_NONATOMIC 等 */objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
  • objc_getAssociatedObject(id object, void *key)
/** *  获取关联的对象 * *  @param object 调用我的类,常见的是self *  @param key    一个关联的key值。有点类似,字典的key和广播的Name */objc_getAssociatedObject(id object, void *key)
  • objc_removeAssociatedObjects(id object)
/** *  打断对象的所有关联 * *  @param object 要删除关联的对象,常见的是self */objc_removeAssociatedObjects(id object)

tips: 使用objc_setAssociatedObject等,需要引入头文件 #import objc/runtime.h

二 关联的主要作用是扩展属性。

  • 主要作用是当属性和全局变量不能使用的时候进行扩展属性,说白了就是在我配合category会更好的效果,为什么?因为使用时需要key值,一般是一个不可变的字符串,如果在一类中大量的调用我会产生很多不同的key值,这样不便于维护

  • 类别是不可以添加属性的。平常看到在 category 中 写了 @property 实际是生成2个方法罢了

三 应用:

3.1. 用UIAlertview来示例关联与方法交换

如果要给UIAlertview加上一个block 的点击事件,一般的做法是重写UIAlertview,在子类中加上点击的block。这样耦合度太高了,如果我们能够写一个category实现alertview的点击block 就好了,但是category是不允许属性的,所以我们得用另外一种方式实“现曲线救国”。

//UIAlertView+Associate.h#import <UIKit/UIKit.h>typedef void (^bSuccessBlock)(NSInteger buttonIndex);@interface UIAlertView (Associate)<UIAlertViewDelegate>-(void)showWithBlock:(bSuccessBlock)block;@end
//UIAlertView+Associate.m#import "UIAlertView+Associate.h"#import <objc/runtime.h>static const char alertKey;@implementation UIAlertView (Associate)-(void)showWithBlock:(bSuccessBlock)block{    if (block) {        objc_setAssociatedObject(self, &alertKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);        self.delegate = self;    }    [self show];}-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{    bSuccessBlock block = objc_getAssociatedObject(self, &alertKey);    block(buttonIndex);}@end

使用

 UIAlertView *tAlertView = [[UIAlertView alloc]initWithTitle:@"me" message:@"" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"其他", nil];   [tAlertView showWithBlock:^(NSInteger buttonIndex) {       NSLog(@"%ld",(long)buttonIndex);   }];

拓展

1 @property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的?

“属性” (property)作为 Objective-C 的一项特性,主要的作用就在于封装对象中的数据。Objective-C 对象通常会把其所需要的数据保存为各种实例变量。实例变量一般通过“存取方法”(access method)来访问。其中,“获取方法” (getter)用于读取变量值,而“设置方法” (setter)用于写入变量值。

1.1 @property 的本质是什么?

@property =ivar(实例变量)+access method (存取方法= getter + setter);

@interface Person : NSObject@property NSString *firstName;@property NSString *lastName;@end//相当于下边,生成生成存取方法+实例变量@interface Person : NSObject    NSString *_firstName;    NSString *_lastName;}- (NSString *)firstName;- (void)setFirstName:(NSString *)firstName;- (NSString *)lastName;- (void)setLastName:(NSString *)lastName;@end
1.2 ivar、getter、setter 是如何生成并添加到这个类中的?

“自动合成”( autosynthesis):完成属性定义后,编译器会自动编写访问这些属性所需的方法。
这个过程由编译器在编译期执行,所以编辑器里看不到这些“合成方法”(synthesized method)的源代码。

//属性定义后会自动生成两个实例变量,其名称分别为 _firstName 与 _lastName@interface Person : NSObject@property NSString *firstName;@property NSString *lastName;@end//或者//也可以通过 @synthesize 语法来指定实例变量的名字.@implementation Person@synthesize firstName = _myFirstName;@synthesize lastName = _myLastName;@end
1.3 属性是怎么实现的
  • OBJC_IVAR_类名$属性名称 :该属性的“偏移量” (offset),这个偏移量是“硬编码” (hardcode),表示该变量距离存放对象的内存区域的起始地址有多远。
  • setter 与 getter 方法对应的实现函数
  • ivar_list :成员变量列表
  • method_list :方法列表
  • prop_list :属性列表

也就是说我们每次在增加一个属性:
(1)系统都会在 ivar_list 中添加一个成员变量的描述,
(2)在 method_list 中增加 setter 与 getter 方法的描述,
(3)在prop_list 中增加一个属性的描述,
(4)然后计算该属性在对象中的偏移量,
(5)然后给出 setter 与 getter 方法对应的实现,
(6)在 setter 方法中从偏移量的位置开始赋值,在 getter 方法中从偏移量开始取值,为了能够读取正确字节数,系统对象偏移量的指针类型进行了类型强转.
1.4 @protocol 和 category 中如何使用 @property

  • 在 protocol 中使用 property 只会生成 setter 和 getter 方法声明,我们使用属性的目的,是希望遵守我协议的对象能实现该属性
  • category 使用 @property 也是只会生成 setter 和 getter 方法的声明,如果我们真的需要给 category 增加属性的实现,需要借助于运行时的两个函数:
    • objc_setAssociatedObject
    • objc_getAssociatedObject

1.[Objective-c 高阶语法] 关联与方法交换
2.ios设计模式
3.@property 的本质是什么?
4.iOS Category中添加属性和成员变量的区别
5.Objective-C类成员变量深度剖析
6.让我们来谈谈 @property

0 0