Skip navigation.
 
mlRe: Bypassing Interface Builder
FROM : Uli Kusterer
DATE : Thu May 15 20:48:45 2008

Am 15.05.2008 um 18:40 schrieb Johnny Lundy:
> 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.



  Just like you'd do without NIBs, yes.

> 4. Write an -init method that doesn't instantiate anything.


  Well, init gets called when your object is instantiated, it doesn't 
instantiate the object itself. Of course, init can instantiate *other* 
objects that your object needs, like an NSTextField would probably 
instantiate an NSMutableString object to hold whatever text it's 
supposed to display.

> 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.


  +initialize is a class method, hence the "+". It is kind of a 
constructor for the class (as opposed to the -init methods that get 
called on objects. This was one of the harder parts in Objective C, to 
teach oneself to read + to mean "class method" and - to mean "object/
instance method".

> 6. Compile.
> 7. In IB, make an NSTextField and read in my class header file.


  Not related, and as others have said, IB3 reads your classes 
automagically as soon as you save them.

> 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.


  If that is all you did, then an object of your class was never 
instantiated. The only thing you got was an NSObject. The least you'll 
have to do is go to the "identity" pane of the inspector for this 
instance and type the name of your class into the "custom class" field.

> Somehow, doing the above steps must have created an instance of my 
> class, as one instance method can call another.


  What do you mean by 'one instance method can call another' ? Who is 
calling whom, how? If you just created this object, and nobody else 
has an outlet pointing to it, then while it was instantiated, nobody 
can call a method on it, because nobody has a pointer to it. Someone 
needs to have an outlet or a binding to it to call a method on it (or 
if your object has an action, then it'll probably pass a pointer to 
itself as the sender of that action, so whoever is the target could 
send a message back then, etc. etc.)

> I  know that dragging out the NSObject made an instance, but my 
> class does not know about it.


  What? How? Who? I'm not following you here. When you drag an 
NSObject from the palette, you essentially tell IB to call alloc and 
init on that icon's "custom class" (or on a generic NSObject if you 
don't specify a custom class). That is how your object gets 
instantiated: NSNibLoading calls alloc to get a block of memory the 
size of your object, and your init method then sets that block of 
memory up in the appropriate way.

> 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?


  Well, the object you drag out is the instance. Though if it's just 
an NSObject, you'll probably find your console full of error messages 
that the binding to that property can't be established, because 
NSObject doesn't have these properties.

> Strangely enough, the "hard" APIs like NSURLConnection were easy for 
> me, and worked the first time, because the documentation was 
> extensive and said exactly what the API parameters were for. Not so 
> for trivially simple things like instantiating an object, or even 
> worse, explaining what all the myriad of popups and checkboxes in an 
> IB Bindings pane do. The tool tips are a complete joke - all they do 
> is repeat the label of the item.


  Actually, they've been very helpful to me today. But it depends on 
what tool tips you look at.

  And don't feel disheartened: Bindings, as the documentation states, 
are an advanced topic. It's OK if you start out with properties, 
connections and target/action, and write the rest of the code yourself 
for now. Once you feel familiar with that, go back to bindings. Once 
you are intimately familiar with what manual work is involved in a 
Cocoa application, you'll realize how bindings can save you work there 
because they replace this or that piece of code you had to hand-write 
before. You'll essentially know what bindings do under the hood.

>> That object goes to the instance. You dragged out an *object*, an
>> instance, so that's what you get. I expected that, myself, so never
>> got confused by the name being the class name, but I can see how one
>> could be.
>>

> 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."


  Yes, if you specify the class name as the target, then the message 
will go to the class. If you want to message an actual instance, i.e. 
an object, you need a pointer to that object. Whether you name your 
object "MyClass" or "George" in the NIB doesn't matter, you still 
won't be able to call it as [Peter somemessage]. What you need to do 
instead is add an outlet to whatever object is sending this message, 
and control-drag to make IB aware that you want this outlet to point 
at that particular instance.

> 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.



  Setting the *name* does not set the *class*. As I said, the name is 
*completely ignored*, it is simply for you when you're using IB so you 
can more easily tell the two blue boxes apart. To change the class, 
type it into the "custom class" field on the "identity" pane of the 
inspector.

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


  Well, in the case of the application object you generally don't do 
that. But in the case of an NSDocument-based application or an 
NSWindowController subclass, both of which load their own NIBs, the 
file's owner is the instance of your NSDocument or NSWindowController 
subclass (or whatever), which loaded the NIB when you created an 
instance of that subclass.

  Since creating that NSWindowController was what caused the NIB to be 
loaded, the window controller isn't a regular object in the NIB, it is 
the owner of that NIB. If you dragged an NSWindowController into the 
NIB, you'd get a second NSWindowController instance. That's not what 
you want. That's where File's Owner comes in: It is a placeholder for 
the object that loaded this NIB so you can bind to it, connect to it, 
point outlets at it etc.

  Does that clarify things a bit? I'm not quite sure how I can phrase 
this differently.

> File's Owner is not one of my classes,


  File's Owner is *not* a class. It is simply a name (remember, names 
are mostly ignored) for an instance. For the instance that asked 
NSNibLoading to instantiate the objects in this NIB for it.

> and thus wouldn't know about any of my classes' properties to bind to.


  Look at the "custom class" of the File's Owner. In general, for a 
main NIB that will be type NSApplication, while for an NSDocument's 
NIB it will be MyDocument or whatever name you gave it when you 
created it. If you create your own NIB without using any of the 
existing templates, you may have to set that object's custom class to 
be that of the object that loads the NIB.

> 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.
>



Cheers,
-- Uli Kusterer
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de

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