【问题标题】:Within an IBAction, "self" refers only to the first instance of an object在 IBAction 中,“self”仅指对象的第一个实例
【发布时间】:2014-07-12 00:21:37
【问题描述】:

这是一个基本的 Objective-C 问题,但我很困惑,我还没有在其他地方找到答案。我有一个自定义类,我们将调用 MyObject。在我的 MainMenu.xib 中,我有一个按钮可以触发该自定义类中的 IBAction。在同一个 NIB 文件中,我有一个 MyObject 类的对象(蓝色立方体),因此我可以将按钮“连接”到自定义类中的方法(作为 IBAction)。这一切都很好。

我需要创建多个 MyObject 实例,并且我在该对象上调用了几个方法,其中一些是简单(无效)方法,都在类中,其中一些是链接到MainMenu.xib 文件。

当我在不是 IBActions 的 (void) 本地方法中使用“self”时,它总是引用当前活动的类实例,正如我想要的那样,并且期望。当我在 IBActions 中使用“self”时,它总是只引用该自定义对象的第一个实例。

我可以通过在单独的(指向 MyObject 的指针)变量中跟踪当前活动的实例来轻松解决这个问题,但我想知道为什么“self”在某些方法中按预期工作,但在 IBActions 中却没有,甚至想它们都在一个类文件中。

以下代码 sn-p 旨在解释我的意思(我希望它有效!):

@implementation MyObject

MyObject *theActiveObject;

- (instancetype) init {
    self = [super init];
    if (self)
        theActiveObject = self;
    return self;
    }

- (IBAction)showSelf:(id)sender {
    NSLog(@"from an IBAction, my SELF is: %p theActiveObject: %p", self, theActiveObject);
    [self showSelfOther];
    }

- (void) showSelfOther {
    NSLog(@"from a plain method: SELF is: %p theActiveObject: %p", self, theActiveObject);
    }

如果我将几个活动对象的第一个对象设为活动对象(例如,通过单击其窗口),那么我得到的结果(使用模拟地址)是:

来自 IBAction,我的 SELF 是:0xaddress01 theActiveObject: 0xaddress01

从一个普通的方法:SELF is: 0xaddress01 theActiveObject: 0xaddress01

如果我然后单击自定义类的第二个对象的窗口,我会得到:

来自 IBAction,我的 SELF 是:0xaddress01 theActiveObject: 0xaddress02

从一个普通的方法:SELF is: 0xaddress02 theActiveObject: 0xaddress02

我不明白为什么在 IBAction 的第二个对象上使用的“self”指向第一个对象。任何有助于理解这一点的帮助将不胜感激!

针对 Ken Thomases 的回答添加的评论(谢谢,Ken):

谢谢,这个答案很明确,也很有意义。正如我所说,我可以通过使用单独维护的变量(或数组)来保存 MyObject 的每个实例来轻松解决这个问题——无论如何我都需要这样做。所以我的问题变成了理论上的:这是做到这一点的“正确”方法吗?我的 MainMenu.xib 中有几个按钮(它们应该在哪里),它们连接到自定义类中的方法。我只能以这种方式将它们与代表 MainMenu.xib 中的自定义类的“蓝色立方体”对象连接起来,并且我不能在这些方法中使用“self”。这种“感觉”是错误的,因为我在类的所有其他方法中都使用了“self”,并且它按我预期的方式工作——它随着每个实例的变化而变化,在这些方法中。

那么这是一种正确的方法吗,或者我应该使用其他策略来在自定义类的所有方法中使用“self”,如果是,那是什么策略?

我看到自定义类的第一个实例是在启动时加载 MainMenu.xib 时创建的,因为我在该文件中有“蓝色立方体”。我有蓝色立方体,因为没有它,我不知道有任何其他方法可以将按钮连接到自定义类的方法。有没有办法做到这一点,我还没有想出来?如果是这样,我希望我可以消除蓝色立方体,从而消除第一个自动创建的自定义对象实例。因此,我可以在自定义类的所有方法中以相同的方式使用 self。

非常感谢您对这个主题的任何启发。另一方面,我不明白为什么我最初的问题有两个反对票。太笨了?

【问题讨论】:

  • self 总是指调用方法的实例,而不是其他任何东西。

标签: objective-c macos cocoa self ibaction


【解决方案1】:

MainMenu.xib 包含应用程序主菜单的存档。 NIB 在应用启动时加载,其中的菜单未归档并安装为运行时的实际主菜单。

显然,根据您的说法,您还在 NIB 中实例化了 MyObject 类的实例。此实例存档在 NIB 中。 (这里我略去了一些不重要的细节。)当 NIB 被加载时,该实例将被取消归档并成为您应用进程中的“活动对象”。

您在 NIB 中与该对象建立的任何连接都将与该实例建立。特别是,您显然已将某些按钮的目标直接连接到该实例。这些连接是固定的。这些按钮以该实例而不是其他实例为目标。

因此,当您按下按钮时,将调用(固定)目标上的操作方法。

相比之下,当您在代码中调用方法时,您指定了接收者,您可以随心所欲地动态化。如果您的代码逻辑如此,您可以将这些消息发送到不同的实例。

这听起来有点像您希望您的按钮针对 NIB 的第一响应者。这是一个对象链的占位符,从具有焦点的任何视图开始,一直到其包含的窗口,然后是应用程序,因此它会随着焦点的变化而变化。但是,如果没有更多详细信息,很难确定这是您想要的。

【讨论】:

    【解决方案2】:

    它并不总是指同一个实例。之所以在这里是因为您应用中的控件仍然具有与之前相同的目标,大概是这样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-04
      • 1970-01-01
      • 2018-01-12
      • 1970-01-01
      • 2017-02-25
      • 2010-12-30
      • 2021-11-24
      相关资源
      最近更新 更多