在Categories中使用Associative References为class添加伪实例变量
2011-07-07 15:03
549 查看
在ios 3.1和 os x 10.6系统里,苹果公司在objective-c运行时添加了一个associative references
特性。从本质上来说,这意味着每人上对象都有一个optional dictionary,你可以在这个dictionary
中添加键/值对。
这是一个很强大的特性,特别当考虑到objective-c原本有的一个categories特性。然而,
categories不允许你为类增加额外的实例变量。而使用associative references,为类添加伪
实例变量变得非常容易。
在objective-c运行时提供的c语言的api里,你可以为一个对象添加键/值对,然后可以用下面两
个方法来对它进行存取:
来说,我们就实现了一个完全不透明的伪实例变量。
接收intergers类型数据,有时候这会成为一个制约的因素)。
我们像下面这样来写"object tag" category的类:
@interface UIView (ObjectTagAdditions)
@property (nonatomic, retain) id objectTag;
- (UIView *)viewWithObjectTag:(id)object;
@end
使用associative references,属性的实现非常直接:
static const char *ObjectTagKey = "ObjectTag";
@implementation UIView (ObjectTagAdditions)
@dynamic objectTag;
- (id)objectTag {
return objc_getAssociatedObject(self, ObjectTagKey);
}
- (void)setObjectTag:(id)newObjectTag {
objc_setAssociatedObject(self, ObjectTagKey, newObjectTag, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
...
通过在set方法中指定OBJC_ASSOCIATION_RETAIN_NONATOMIC,我们告诉编译器在运行时retain
这个变量的值。其它可用来指定的标识是:
- (UIView *)viewWithObjectTag:(id)object {
// Raise an exception if object is nil
if (object == nil) {
[NSException raise:NSInternalInconsistencyException format:@"Argument to -viewWithObjectTag: must not be nil"];
}
// Recursively search the view hierarchy for the specified objectTag
if ([self.objectTag isEqual:object]) {
return self;
}
for (UIView *subview in self.subviews) {
UIView *resultView = [subview viewWithObjectTag:object];
if (resultView != nil) {
return resultView;
}
}
return nil;
}
特性。从本质上来说,这意味着每人上对象都有一个optional dictionary,你可以在这个dictionary
中添加键/值对。
这是一个很强大的特性,特别当考虑到objective-c原本有的一个categories特性。然而,
categories不允许你为类增加额外的实例变量。而使用associative references,为类添加伪
实例变量变得非常容易。
在objective-c运行时提供的c语言的api里,你可以为一个对象添加键/值对,然后可以用下面两
个方法来对它进行存取:
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) id objc_getAssociatedObject(id object, const void *key)如果我们把上述方法的调用包装在属性的自定义getter和setter方法里,对使用我们的api的使用者
来说,我们就实现了一个完全不透明的伪实例变量。
Using objects to tag UIViews
下面这个例子里,我们想要增加一个对象来做为一个view的tag(而UIView已经存在的tag属性只能接收intergers类型数据,有时候这会成为一个制约的因素)。
我们像下面这样来写"object tag" category的类:
@interface UIView (ObjectTagAdditions)
@property (nonatomic, retain) id objectTag;
- (UIView *)viewWithObjectTag:(id)object;
@end
使用associative references,属性的实现非常直接:
static const char *ObjectTagKey = "ObjectTag";
@implementation UIView (ObjectTagAdditions)
@dynamic objectTag;
- (id)objectTag {
return objc_getAssociatedObject(self, ObjectTagKey);
}
- (void)setObjectTag:(id)newObjectTag {
objc_setAssociatedObject(self, ObjectTagKey, newObjectTag, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
...
通过在set方法中指定OBJC_ASSOCIATION_RETAIN_NONATOMIC,我们告诉编译器在运行时retain
这个变量的值。其它可用来指定的标识是:
OBJC_ASSOCIATION_ASSIGN,
OBJC_ASSOCIATION_COPY_NONATOMIC,
OBJC_ASSOCIATION_RETAIN,
OBJC_ASSOCIATION_COPY;你可以根据情况使用。
最后,这里还有一段-viewWithObjectTag:method:递归代码,用来查找有这个objectTag的view:
- (UIView *)viewWithObjectTag:(id)object {
// Raise an exception if object is nil
if (object == nil) {
[NSException raise:NSInternalInconsistencyException format:@"Argument to -viewWithObjectTag: must not be nil"];
}
// Recursively search the view hierarchy for the specified objectTag
if ([self.objectTag isEqual:object]) {
return self;
}
for (UIView *subview in self.subviews) {
UIView *resultView = [subview viewWithObjectTag:object];
if (resultView != nil) {
return resultView;
}
}
return nil;
}
相关文章推荐
- 使用eclipse JDT compile class,解决 无法确定 X 的类型参数;对于上限为 X,java.lang.Object 的类型变量 X,不存在唯一最大实例
- 使用eclipse JDT compile class,解决 无法确定 X 的类型参数;对于上限为 X,java.lang.Object 的类型变量 X,不存在唯一最大实例
- 使用eclipse JDT compile class,解决 没法确定 X 的类型参数;对于上限为 X,java.lang.Object 的类型变量 X,不存在唯一最大实例
- 使用eclipse JDT compile class,解决 无法确定 X 的类型参数;对于上限为 X,java.lang.Object 的类型变量 X,不存在唯一最大实例
- 详解Objective-C的meta-class ,runtime创建类,添加实例变量
- 第六种方式,python使用cached_property缓存装饰器和自定义cached_class_property装饰器,动态添加类属性(三),selnium webdriver类无限实例化控制成单浏览器。
- 【Objective-C Runtime动态加载】---动态创建类Class 动态创建类Class,动态添加Class成员变量与成员函数,动态变量赋值与取值,动态函数调用等方法 a.使用objc_
- Linux使用笔记4-添加用户变量(设置自己的命令,修改默认python版本等)
- instanceof 变量是否属于某一类 class 的实例
- 多iframe使用tab标签方式添加、删除、切换的处理实例
- 为类添加实例变量 (Associative References)
- C#.NET常见问题(FAQ)-如何使用变量动态添加控件
- PHP Session 变量的使用方法详解与实例代码
- [Ruby笔记]28.Ruby @@class_variables 类变量 vs @instance_variable 实例变量
- SQL/PLSQL:Oracle绑定变量使用实例 define undefine verify
- Windows7系统如何设置添加环境变量以供软件使用
- MFC STATIC,Picture控件使用及无法添加变量的问题
- Salesforce中使用Apex Test Class(测试类)测试Extension类型实例
- php中soap的使用实例以及生成WSDL文件,提供自动生成WSDL文件的类库——SoapDiscovery.class.php类
- java反射学习笔记(3)---使用Class来获取方法、成员变量、构造函数信息