Re: Bypassing Interface Builder
Re: Bypassing Interface Builder
- Subject: Re: Bypassing Interface Builder
- From: Uli Kusterer <email@hidden>
- Date: Thu, 15 May 2008 20:48:45 +0200
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
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden