这两天在想着写一个自己的开源框架,类似MJRefresh那种。因为是自己第一个框架,也没有这方面的经验,还在摸索中。
- 初步设想是给UIScrollview添加一个分类,在其中添加相关的属性和方法,但是在添加属性的时候遇到了些麻烦。比如以下:
#import <UIKit/UIKit.h>
@interface UITableViewController (ZLRefresh)
@property (nonatomic, strong) NSObject *object;
@end
此时编译器会报警告,大意是此分类无法合成属性的相关实例变量。
- 查阅了相关资料,比如在《Effective Objective-C 2.0》中就提供了可以使用关联对象的方法实现在分类中添加属性(虽然作者在书中反复强调最好不要这么做...)。如下:
#import "UITableViewController+ZLRefresh.h"
#import <objc/runtime.h>
static const char* kObjectPropertyKey = "kObjectPropertyKey";
@implementation UITableViewController (ZLRefresh)
- (NSObject *)object{
return objc_getAssociatedObject(self, kObjectPropertyKey);
}
- (void)setObject:(NSObject *)object{
objc_setAssociatedObject(self,
kObjectPropertyKey,
object,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
PS:此处注意要导入<objc/runtime.h>这个头文件!
-
好吧,我发现脑海中对这个所谓关联对象一点映像都木有QAQ,继续翻阅资料,在书中(依然是《Effective objc2.0》)找到如下:
- 可以给对象关联许多对象,这对象通过键来区分。
2.在存储对象值得时候,可以指明“存储策略”(storage policy),用以维护相应的内存,(比如上面的
OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
3.可以用以下的方法管理关联对象:
-
void objc_setAssociatedObject(<#id object#>, <#const void *key#>, <#id value#>, <#objc_AssociationPolicy policy#>)
此方法用以给定的键和策略为某对象设置关联对象值。 -
id objc_getAssociatedObject(<#id object#>, <#const void *key#>)
此方法根据给定的键从某对象中获取相应的关联对象值。 -
objc_removeAssociatedObjects(<#id object#>)
此方法用于移除指定对象的全部关联对象。 - 可以看到这个所谓的关联对象和我们平时所使用的NSDictionary很像,但是作者也强调了,两者之间有个重要的区别:设置关联对象的key是个不透明的指针(
void*
)。比如在两个键上调用isEqual:
方法返回的值是yes,那么dic就认为是二者相等;而然在设置关联对象值时,若想令两个键匹配到同一个值,则二者必须是完全相同的指针才可以。故设置关联对象的键通常是 静态全局变量