您的位置:首页 > Web前端

在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里,你可以为一个对象添加键/值对,然后可以用下面两
个方法来对它进行存取:
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;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐