-2

This is a basic Objective-C question, but I'm mystified and I haven't found an answer elsewhere. I have a custom class we'll call MyObject. In my MainMenu.xib, I have a a button which triggers an IBAction within that custom class. In the same NIB file, I have an object (blue cube) of class MyObject, so I can "wire" the button to a method (as an IBAction) within the custom class. This all works fine.

I need to make multiple instances of MyObject, and there are several methods I call on that object, some of which are simple (void) methods, all within the class, and a few of which are IBActions linked to buttons in the MainMenu.xib file.

When I use "self" within the (void) local methods which are not IBActions, it always refers to the currently active instance of the class, as I want, and expect. When I use "self" within the IBActions, it always refers ONLY to the first instance of that custom object.

I can easily work around this by keeping track of the currently active instance in a separate (pointer to MyObject) variable, but I want to know why "self" works as expected in some methods, but not in IBActions, even thought they're all within a single class file.

The following code snippet is intended to explain what I mean (I hope it works!):

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

If I make the FIRST object of several the active object (by clicking its window, for example), then the results I get (using simulated addresses) are:

from an IBAction, my SELF is: 0xaddress01 theActiveObject: 0xaddress01

from a plain method: SELF is: 0xaddress01 theActiveObject: 0xaddress01

If I then click in the window of the second object of my custom class, I get:

from an IBAction, my SELF is: 0xaddress01 theActiveObject: 0xaddress02

from a plain method: SELF is: 0xaddress02 theActiveObject: 0xaddress02

I don't see why "self", used on the SECOND object from an IBAction, is pointing to the first object. Any assistance in understanding this would be most appreciated!

Comments Added in response to an answer from Ken Thomases (thanks, Ken):

Thanks, this answer is clear and makes sense. As I said, I can easily work around this by using a separately maintained variable (or array) to hold each instance of MyObject - which I need to do anyway. So my question becomes theoretical: is this the "correct" way to do this? I have a couple of buttons in my MainMenu.xib (where they should be) that are wired to methods in a custom class. I am only able to wire them this way with a "blue cube" object representing the custom class in MainMenu.xib, and I cannot use "self" within the those methods. This "feels" wrong because I use “self” in all other methods of the class, and it works as I expect - it changes with each instance, in those methods.

So is this a correct approach, or should I use some other tactic to be able to use “self” in ALL methods of the custom class, and if so, what is that tactic?

I see that the first instance of the custom class is created when MainMenu.xib is loaded at startup, BECAUSE I have the “blue cube” for it in that file. I have the blue cube because I don’t know of any other way to wire the buttons to the methods of the custom class without it. Is there a way to do that that I haven’t figured out? If so, I would expect that I could eliminate the blue cube, thereby eliminating the first automatically created instance of the custom object. And accordingly, I could then use self the same way, in all methods of the custom class.

Any light that you can shed on this topic is very much appreciated. On the other hand, I don’t understand why my original question has two down votes. Too dumb?

user1912017
  • 7
  • 1
  • 2
  • 7
    `self` always refers to the instance on which the method was called and never anything else. – nhgrif Jul 12 '14 at 00:26

2 Answers2

1

The MainMenu.xib contains an archive of the main menu of your app. The NIB is loaded at app start-up and the menu within it is unarchived and installed as the actual main menu for runtime.

Apparently, from what you say, you've also instantiated an instance of your MyObject class in the NIB. This instance is archived within the NIB. (I'm waving away some details which aren't important here.) When the NIB is loaded, that instance is unarchived and becomes a "live object" within your app's process.

Any connections that you establish within the NIB to that object are made to that instance. In particular, you have apparently directly connected the target of some buttons to that instance. Those connections are fixed. Those buttons target that instance and no other.

So, when you press the buttons, the action method on the (fixed) target is invoked.

By contrast, when you invoke methods in code, you specify the receiver and you can be as dynamic as you like. You can send those messages to a different instance if that's what the logic of your code does.

It sounds a bit like you want your buttons to target the First Responder of the NIB. That's a placeholder for a chain of objects starting at whatever view has the focus up to its containing window and then the app, so it changes as the focus changes. However, it's hard to be sure that's what you want without more details.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
0

It doesn't always refer to the same instance. It does here because the controls in your app still have the same target they did before, presumably.

Chuck
  • 234,037
  • 30
  • 302
  • 389