【问题标题】:Obj-c runtime: find what class another class is a property ofObj-c 运行时:查找另一个类是哪个类的属性
【发布时间】:2014-02-07 16:52:30
【问题描述】:

假设我有这个:

@interface ThingManager : NSObject
@property Thing *aThing;
@end

有没有办法让aThing 在运行时知道它是ThingManager 的属性?

【问题讨论】:

  • 您可能有一个未分配给该属性的 Thing 实例。然后将其分配给该属性。那时,实例完全不知道发生了这种情况。它不应该。如果您需要这些知识,则需要显式更新添加到 Thing 类的一些适当状态以跟踪此类信息。
  • @rmaddy 所以你是说我可以在Thing 上添加一个类方法来跟踪其实例被设置为属性的位置?
  • 我是说你应该添加你想要跟踪的任何内容。如果每个实例都需要知道,则将其设为实例方法。您的要求太模糊,无法给出更详细的答案。

标签: iphone objective-c macos objective-c-runtime


【解决方案1】:

你从问题开始:

有没有办法让aThing 在运行时知道它是ThingManager 的属性?

虽然到目前为止还没有完全清楚答案,但假设您希望aThing 能够确定ThingManger一个实例 是否正在管理它。

所以此时我们知道ThingManger 类知道Thing 类,而您现在似乎想要反过来——您问Thing 可以找到它的ThingManager 吗?

但是当有人回答你评论时

所以ThingThingManager 需要相互了解?嗯……不适合松耦合。

嗯...如果您不想让ThingManagers 知道Thing 是什么,Thing 怎么能问它?

每个人对你的问题的解释都错了吗?

也许您关心的不是松散耦合,而是强引用循环?如果两者相互了解,并在此过程中形成一个强大的循环,那么在您的应用程序需要其中任何一个之后,他们就有可能让彼此存活很长时间 - 这是担心吗?

但是@DrummerB 解决了这个问题——你在Thing 上使用了一个弱属性,它引用了它的管理ThingManager。所以看起来强参考周期也不是你关心的问题......

然后你评论:

有没有办法在运行时查看谁在引用对象?

正如一般所说,这是一个非常不同的问题。对此的简短回答是否定的[*]。

您是否问是否可以编写一个方法,Thing 可以调用该方法来查找管理它的ThingManager,而无需在Thing 实例和ThingManager 实例之间维护任何引用?

如果是这样,这里是一个大纲算法:

  1. ThingManager 类保留所有创建和活动 实例的集合。活着的要求要求这个集合是某种弱集合(设计你自己的或搜索弱集合)。
  2. ThingManager 添加一个class 方法,用于查找Thing 的管理器,例如类似+ (ThingManager *) managerFor:(Thing *)thing
  3. 当您的Thing 实例需要了解他们的经理时,请致电[ThingManager managerFor:self]

这当然不能解决您对松散耦合的担忧——这两个类仍然必须知道彼此的存在......

这让您回到让Thing 拥有manager 属性的直接解决方案。如果您想减少耦合,您可以将此属性键入为id,因此它是任何旧对象,或id<SomeMinimalManagerProtocol>,因此它的任何旧对象提供它实现您在协议@987654351 中定义的一些最小管理方法集@。

看看NSWindowNSWindowController - 他们了解彼此。

HTH


[*] 长答案是 (Objective-)C(++) 并非旨在确保可以找到所有引用。这就是为什么您会听到诸如“保守垃圾收集”之类的短语。有一个仅针对 Objective-C 对象的垃圾收集器,它由运行时的内部更改支持,但现在已弃用,并且应用程序无法轻松访问其机制以应用于其他用途。

【讨论】:

  • 是的,我的基本问题确实是:Isn't there a way to see who's referencing an object at runtime?,我实际上想知道在我的简单场景下是否可以将 Objective-C 运行时方法用于此目的。因为松耦合,Thing 知道 ThingManager 会破坏松耦合,我不希望这样。所以我喜欢你在Thing 上拥有一个属性的解决方案,它可以让你弄清楚它的ThingManager 是什么。
  • 我猜[NSHashTable weakObjectsHashTable][NSPointerArray weakObjectsPointerArray] 将是您大纲算法中第 1 步的不错选择?
  • @Eric - 这两个都是包含弱引用并且可以使用的集合。如果您打算走这条路并希望创建和丢弃许多ThingManagers,请记住您可能需要“清理”空引用的集合。
  • “清理 NULL 引用的集合”?但是那有什么用呢? "If ptr is NULL no operation is performed",对吧?
  • @Eric - 您的集合将为您创建的每个ThingManager 获得一个条目,并且一旦该对象死亡,该条目将设置为 null。随着时间的推移,您可能会拥有一个主要由 null 组成的非常大的集合 - 因此删除它们可能是减少内存使用的明智之举。如果你只打算创建少数ThingManagers,那么这种管家可能不值得。
【解决方案2】:

除非你告诉它,否则不会。

您可以将 ThingManager 弱属性添加到 Thing 并在 ThingManager 中实现 setter,如下所示:

- (void)setAThing:(Thing *)thing {
    if (_aThing != thing) {
        _aThing = thing;
        _aThing.manager = self;   // this is the relevant line
    }
}

【讨论】:

  • 好的。你如何“告诉它”?
  • 那么ThingThingManager 需要互相了解吗?嗯...不适合松散耦合。
  • 没有办法让属性“神奇地”知道引用它的任何对象。如果你想要更松散的耦合,也许你应该应用委托模式?
  • 有没有办法在运行时查看谁在引用对象?
【解决方案3】:

除非您为 aThing 属性设置了一个自定义设置器,该设置器在 Thing 对象上设置了一些东西来告诉它它是。您可以让aThing setter 方法设置一个您添加到Thing 的属性,告诉它谁是它的经理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-16
    • 2020-07-09
    • 1970-01-01
    • 2021-11-26
    • 2015-08-31
    • 2020-09-01
    • 1970-01-01
    相关资源
    最近更新 更多