【问题标题】:Any gotchas with objc_setAssociatedObject and objc_getAssociatedObject?objc_setAssociatedObject 和 objc_getAssociatedObject 的任何陷阱?
【发布时间】:2023-03-19 16:36:01
【问题描述】:

我正在研究向所有 UIView 实例添加属性(在本例中为整数)的方法,无论它们是否是子类。在一个类别中使用 objc_setAssociatedObject()objc_getAssociatedObject() 是否是 Apple 认可的适当方式?

我听说有人担心这会构成“运行时破解”,并可能导致难以追踪和调试的问题。有没有其他人见过这种类型的问题?有没有更好的方法来为所有 UIView 实例添加一个整数属性而不进行子类化?

更新:我不能只使用tag,因为这需要在已经将tag 用于其他用途的代码库中使用。相信我,如果我可以为此使用tag,我会的!

【问题讨论】:

  • 回复有点晚,但它可能对其他不想深入并创建类别和新 customTag 的人有用。您可以通过将多个数字分配到特定数字来将多个数字存储在同一个标​​签中,例如分配 view.tag = (view.tag * 100) + myNumber; 并将其取回 myNumber = view.tag % 100 以获取原始标签,请使用 originalTag = view.tag / 100
  • 好主意。根据您的操作,您还可以使用NS_OPTIONS 并创建位掩码。

标签: ios objective-c objective-c-runtime


【解决方案1】:

当你想在一个类上伪造一个 ivar 时,关联对象会派上用场。它们非常通用,因为您可以将任何对象关联到该类。

也就是说,你应该明智地使用它,并且只用于子类化感觉很麻烦的小事情。

但是,如果您的唯一要求是向所有 UIView 实例添加一个整数,那么 tag 是可行的方法。它已经存在并可供您使用,因此无需对UIView 进行运行时修补。

如果您想用比整数更多的东西(例如通用对象)来标记UIView,您可以定义一个如下所示的类别。

UIView+Tagging.h

@interface UIView (Tagging)
@property (nonatomic, strong) id customTag;
@end

UIView+Tagging.m

#import <objc/runtime.h>

@implementation UIView (Tagging)
@dynamic customTag;

- (id)customTag {
    return objc_getAssociatedObject(self, @selector(customTag));
}

- (void)setCustomTag:(id)aCustomTag {
    objc_setAssociatedObject(self, @selector(customTag), aCustomTag, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

Erica Sadun 最近在blog post 中提出了使用属性选择器作为键的技巧。

【讨论】:

  • 这种模式有一个巨大的缺点,因为它会导致您的类和功能与系统类/功能交错的意大利面条代码未来的重构变得困难(维护也变得困难)。这个特定的示例相对无害,尽管在该属性前面加上您的应用程序独有的东西!
  • @bbum,这是我们唯一会使用这样的东西的地方,它不会比@gabriele-petronella 的答案更复杂。
【解决方案2】:

使用tag。这就是它的目的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    相关资源
    最近更新 更多