在IBAction中,“self”仅指对象的第一个实例

时间:2014-07-12 00:21:38

标签: objective-c macos cocoa self ibaction

这是一个基本的Objective-C问题,但我很神秘,我在其他地方找不到答案。我有一个自定义类,我们将调用MyObject。在我的MainMenu.xib中,我有一个触发该自定义类中的IBAction的按钮。在同一个NIB文件中,我有一个MyObject类的对象(蓝色立方体),所以我可以" wire"自定义类中方法(作为IBAction)的按钮。一切正常。

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

当我使用" self"在(void)本地方法中,不是IBActions,它总是引用类的当前活动实例,如我所愿,并期望。当我使用" self"在IBActions中,它始终只引用该自定义对象的第一个实例。

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

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

@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);
    }

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

来自IBAction的

,我的SELF是:0xaddress01 theActiveObject:0xaddress01

来自普通方法的

:SELF是:0xaddress01 theActiveObject:0xaddress01

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

来自IBAction的

,我的SELF是:0xaddress01 theActiveObject:0xaddress02

来自普通方法的

:SELF是:0xaddress02 theActiveObject:0xaddress02

我不明白为什么" self&#34 ;,在IBAction的SECOND对象上使用,指向第一个对象。理解这一点的任何帮助都将非常感谢!

评论添加回应Ken Thomases的回答(谢谢,肯):

谢谢,这个答案很清楚,也很有道理。正如我所说,我可以通过使用一个单独维护的变量(或数组)来保存MyObject的每个实例 - 我无论如何都需要这样做。所以我的问题变得理论化了:这是"正确的"这样做的方法?我的MainMenu.xib中有几个按钮(它们应该在哪里)连接到自定义类中的方法。我只能用这种方式用蓝色立方体和#34;在MainMenu.xib中表示自定义类的对象,我不能使用" self"在这些方法中。这"感觉"错误,因为我在类的所有其他方法中使用“self”,并且它按照我的预期工作 - 它会随着每个实例在这些方法中发生变化。

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

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

非常感谢您对此主题的任何启发。另一方面,我不明白为什么我原来的问题有两张选票。太笨了?

2 个答案:

答案 0 :(得分:1)

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

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

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

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

相比之下,当您在代码中调用方法时,您可以指定接收器,并且可以根据需要进行动态调整。如果这就是代码的逻辑,那么您可以将这些消息发送到另一个实例。

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

答案 1 :(得分:0)

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