Skip navigation.
 
mlRe: Bypassing Interface Builder
FROM : Paul Sargent
DATE : Thu May 15 20:07:08 2008

On 15 May 2008, at 17:40, Johnny Lundy wrote:
>


> but I am puzzled as to how my new class got instantiated. Here's 
> what I did:
>
> 1. Create the class, the .h and .m files.
> 2. Code the ivars, their @property directives, and their @synthesize 
> directives.
> 3. Write 2 instance methods plus the -init method. There are no 
> class methods, and no IBOutlets.
> 4. Write an -init method that doesn't instantiate anything.
> 5. There is no +initialize method, as I don't understand it. When I 
> have tried to use it, it complains I can't refer to ivars.
> 6. Compile.
> 7. In IB, make an NSTextField and read in my class header file.
> 8. In IB, drag out an NSObject and give it the class name of my new 
> class. I did NOT control-drag anything to anything, and there are no 
> IBOutlets in my code.
>
> Somehow, doing the above steps must have created an instance of my 
> class, as one instance method can call another. I  know that 
> dragging out the NSObject made an instance, but my class does not 
> know about it. So how come the instance methods in my class work? 
> How can the property that I bound to an NSTextField work if there is 
> no instance of my class to hold the property?


I think you're confusing yourself (or others are), and you're tying 
yourself up in knots.

You placed the NSObject in the NIB, you gave it a class name of your 
class. What you're saying when you do that is "When this NIB is 
loaded, create an instance of my class". It's an NSObject you drag 
because NSObject is the super class of all other classes. i.e. your 
class is-a NSObject.

> But [MyClass somemessage] tries to message the class, and I get a 
> "Class MyClass may not respond to somemessage", which makes sense 
> since there is no class method "somemessage."


You're right. [MyClass somemessage] sends a message to the "class 
object", not an instance of the class. For that to work you'd need to 
have +(void) somemessage; defined in MyClass. (Notice the '+' meaning 
class method, as opposed to '-' meaning instance method).

Class methods cannot access instance variables (ivars) because there 
is no instance associated with the call to contains the variables. 
(There might be hundreds of instances of a class in the system, which 
one contains the ivar I want to access) This is why you get the issues 
with +initalize() not being allowed to access ivars. It's a class 
method.

> It won't let me set the class for the second Object. I can type it 
> in, but on hitting Tab or Return or clicking out of the field, the 
> text I entered disappears and it gets replaced with a dimmed 
> "NSObject." I thought it was a glitch in IB, but I discovered that 
> it only does that if you try and set more than one IB object to the 
> same class.


This shouldn't be the case, and suggests you're not doing things quite 
right.

Make sure you are setting the class by editing the Class Identity 
field in the Identity inspector, rather than just changing the name.

I just tried to do this in a new project and succeeded. Here's what I 
did:

1. Started a Cocoa Application Project
2. With 'New File' I added a Objective-C Class called MyClass. I left 
it empty, except I gave it an init method.

- (id) init
{
    self = [super init];
    if (self != nil) {
        NSLog(@"Initialized MyClass");
    }
    return self;
}

3. Opened the NIB and dragged an NSObject into play. I then set the 
class of the Object to MyClass.
4. Added a second MyClass instance in exactly the same way.
5. Saved, build, run, and look at the console.

You'll see that two messages are present, as two instances were 
created. and init is "always" the first message sent to a new instance.


> Right. I can understand that, that the owner is the shared 
> application instance. But why do people bind nib objects to File's 
> Owner?


You're right, in this case the Files Owner is the shared NSApplication 
instance. That's not always true, because NIBs can be loaded by any 
class, but NSApplication is always the owner of the first NIB loaded.

People connect to file's owner to allow the owner to access the 
objects in the NIB. (I use connect rather than bind to avoid 
confusion. Bindings are something different in cocoa-speak)

A common practice is to connect an object to the delegate outlet of 
the NSApplication instance. This allows the NSApplication to send 
messages to your code a predetermined key times. For example, when the 
user selects quit from the menu, the object linked to the delegate 
outlet of the NSApplication will be sent a message to confirm if the 
application should terminate, by sending it the aptly named 
applicationShouldTerminate message. These messages are detailed in the 
NSApplication docs under delegate methods.

If that link wasn't made the NSApplication wouldn't know where to send 
the message. There are no magic connections made between objects 
instantiated by the NIB, and those that are instantiated some other 
way. File's Owner tends to be the gateway between these two worlds, 
with NIB objects being connected to outlets of File's Owner, or (less 
commonly) File's Owner being connected to outlets of NIB objects.

> File's Owner is not one of my classes, and thus wouldn't know about 
> any of my classes' properties to bind to. Does the NSApp shared 
> application instance (represented by File's Owner) somehow know 
> about all properties of all objects in all of my classes? That would 
> be great if it does, I have just never seen it written.


No, it knows that objects connected to certain outlets are likely to 
respond to certain messages (like applicationShouldTerminate above). 
Your class might respond, it might not, it doesn't matter. What it 
does do is give you some points you can hook into and change the 
behaviour coded into NSApplication if you want to.

Related mailsAuthorDate
mlBypassing Interface Builder colo May 14, 16:36
mlRe: Bypassing Interface Builder I. Savant May 14, 17:11
mlRe: Bypassing Interface Builder colo May 14, 17:35
mlRe: Bypassing Interface Builder I. Savant May 14, 17:43
mlRe: Bypassing Interface Builder Andy Lee May 14, 17:50
mlRe: Bypassing Interface Builder colo May 14, 17:53
mlRe: Bypassing Interface Builder I. Savant May 14, 17:58
mlRe: Bypassing Interface Builder David Wilson May 14, 17:59
mlRe: Bypassing Interface Builder I. Savant May 14, 18:01
mlRe: Bypassing Interface Builder I. Savant May 14, 18:05
mlRe: Bypassing Interface Builder Gregory Weston May 14, 18:06
mlRe: Bypassing Interface Builder glenn andreas May 14, 18:13
mlRe: Bypassing Interface Builder Wayne Packard May 14, 18:26
mlRe: Bypassing Interface Builder Andy Lee May 14, 18:37
mlRe: Bypassing Interface Builder Stefan Werner May 14, 18:46
mlRe: Bypassing Interface Builder Bill Bumgarner May 14, 19:00
mlRe: Bypassing Interface Builder Boyd Collier May 14, 19:34
mlRe: Bypassing Interface Builder colo May 14, 19:37
mlRe: Bypassing Interface Builder Julius Guzy May 14, 22:05
mlRe: Bypassing Interface Builder Torsten Curdt May 14, 22:49
mlRe: Bypassing Interface Builder colo May 15, 00:53
mlRe: Bypassing Interface Builder Graham Cox May 15, 01:26
mlRe: Bypassing Interface Builder Graham Cox May 15, 01:41
mlRe: Bypassing Interface Builder colo May 15, 02:14
mlRe: Bypassing Interface Builder Johnny Lundy May 15, 02:15
mlRe: Bypassing Interface Builder Graham Cox May 15, 02:29
mlRe: Bypassing Interface Builder I. Savant May 15, 02:43
mlRe: Bypassing Interface Builder Graham Cox May 15, 02:45
mlRe: Bypassing Interface Builder I. Savant May 15, 02:51
mlRe: Bypassing Interface Builder I. Savant May 15, 02:54
mlRe: Bypassing Interface Builder Andy Lee May 15, 03:02
mlRe: Bypassing Interface Builder Graham Cox May 15, 03:02
mlRe: Bypassing Interface Builder Andy Lee May 15, 03:06
mlRe: Bypassing Interface Builder I. Savant May 15, 03:07
mlRe: Bypassing Interface Builder Andy Lee May 15, 03:08
mlRe: Bypassing Interface Builder I. Savant May 15, 03:09
mlRe: Bypassing Interface Builder I. Savant May 15, 03:15
mlRe: Bypassing Interface Builder Andy Lee May 15, 03:29
mlRe: Bypassing Interface Builder Julius Guzy May 15, 03:35
mlRe: Bypassing Interface Builder I. Savant May 15, 03:37
mlRe: Bypassing Interface Builder Johnny Lundy May 15, 04:33
mlRe: Bypassing Interface Builder Julius Guzy May 15, 04:36
mlRe: Bypassing Interface Builder Johnny Lundy May 15, 04:54
mlRe: Bypassing Interface Builder Graham Cox May 15, 05:43
mlRe: Bypassing Interface Builder Uli Kusterer May 15, 07:50
mlRe: Bypassing Interface Builder Uli Kusterer May 15, 07:55
mlRe: Bypassing Interface Builder Uli Kusterer May 15, 08:15
mlcocoa mentoring (was Re: Bypassing Interface Builder) Torsten Curdt May 15, 15:36
mlRe: cocoa mentoring (was Re: Bypassing Interface Builder) Paul Bruneau May 15, 15:47
mlRe: cocoa mentoring (was Re: Bypassing Interface Builder) Uli Kusterer May 15, 16:08
mlcocoaheads frankfurt (was Re: cocoa mentoring) Torsten Curdt May 15, 16:44
mlRe: cocoa mentoring (was Re: Bypassing Interface Builder) Torsten Curdt May 15, 16:51
mlRe: Bypassing Interface Builder Andy Lee May 15, 17:11
mlRe: Bypassing Interface Builder Johnny Lundy May 15, 18:40
mlRe: cocoa mentoring (was Re: Bypassing Interface Builder) Dennis Munsie May 15, 19:34
mlRe: Bypassing Interface Builder Paul Sargent May 15, 20:07
mlRe: Bypassing Interface Builder Uli Kusterer May 15, 20:48
mlRe: Bypassing Interface Builder Shawn Erickson May 15, 22:20
mlRe: Bypassing Interface Builder Shawn Erickson May 15, 22:30
mlRe: Bypassing Interface Builder Johnny Lundy May 15, 22:32
mlRe: cocoa mentoring (was Re: Bypassing Interface Builder) Torsten Curdt May 15, 23:03