Talk About Network

Google





Mac > Mac Programmer Help > Re: Help with D...
Latest [ Topics | Posts ] Archive Post A New Topic Post a Reply
<< Topic < Post Post 2 of 4 Topic 3712 of 3889
Post > Topic >>

Re: Help with Delegates and File's Owner

by David Phillip Oster <oster@[EMAIL PROTECTED] > Apr 19, 2008 at 11:44 AM

In article 
<be0449a4-03f6-4ba8-a8e1-a3022cce8eb9@[EMAIL PROTECTED]
>,
 Cory <cory.imdieke@[EMAIL PROTECTED]
> wrote:

> Hello, I'm a new Mac App Programmer used to Java and a little bit of C+
> +, and I'm trying to wrap my mind around Delegates. How do they work,
> what are they for, etc? Could anyone give me a basic run-down of them
> and how to use them? Is an AppDelegate the same basic concept of an
> AppController, with a bunch of methods that can be called from any Nib
> in the application?
> 
> The other basic concept that I'm not too firm on is the File's Owner
> in a nib file. What exactly does it point to, and what defines what it
> is? If I open another window from a method in my AppController with a
> button in my Main nib file, is the new window's File's Owner my
> AppController, or the window that called the method in the
> AppController? What's the Owner of the Main nib?
> 
> I have a alright idea of Outlets and so on, basically a way to access
> an object instance in a nib file from code, is that the basic idea?
> 
> Thanks for answering my pretty basic questions!

Table of Contents
  1.) Introduction
  2.) File's Owner
  3.) Object's delegate
  4.) The Responder chain
  5.) Notifications
  6.) Key-Value Observing
  7.) Conclusion


1.) Introduction

There a bunch of inter-related concepts in this part of Mac programming. 
I'll try to explain, but pardon me in advance if I don't do a good job.

2.) File's Owner

A nib file is just an data-structure representation of a network of 
objects. Under the hood of NSApplicationMain, your principal class 
(specified in your Info.plist) loads your principal nib file. (also 
specified in your Info.plist) the sequence of calls eventually calls: 
-[NSNib instantiateNibWithExternalNameTable:] to do the actual work of 
alloc'ing and init'ing the objects described in the file.

You pass in an object, and in the nib file you've set the class of 
"File's Owner", a fictitious instance. NSNib uses the description of the 
class to actually assign to the fields of the object you pass in.

For the main nib of the program, the "File's Owner" is the 
NSApplication. For secondary nib files, the "File's Owner" is a 
NSWindowController. NSWindowController's main job is to turn secondary 
nib files into actual windows on demand.

3.) Object's delegate

You rarely subclass NSApplication. You rarely subclass 
NSWindowController. Instead, you set their delegates to reference on of 
your objects. Both NSApplication and NSWindowController have a list of 
methods that they'll call via:

if ([[self delegate] respondsToSelector:@[EMAIL PROTECTED]
(someMethod)]) {
   [[self delegate] someMethod];
} else {
   [self someMethodDefault];
}

that is, at run time, they'll check if the delegate implements a method, 
and if so, they'll call it, otherwise they'll do some default action.

The set of all methods of a delegate that are called this way is called 
an "informal protocol", by analogy with an Objective-C "protocol", which 
is a set that is checked at compile time, and all the members of the 
protocol MUST be present or you'll get a compile error.  (Although 
Object-C version 2 for OS X Leopard does have additional sup****t for 
writing down informal protocols.)

Note that the delegate of an App is often created because there is an 
instance in the nib file, but nothing REQUIRES delegates to be in nib 
files.

Delegation interacts with reference counting: a NSWindowController 
"has-a" NSWindow (i.e., there is a setter/getter pair that "owns" the 
window.) if objects retained their delegates, there'd be a loop so their 
reference counts would never go to zero, and they'd never be dealloced. 
So the convention is that objects don't [ retain]; their delegates.

4.) The Responder chain

Suppose a menu item in a nib wants to be bound to an IBAction of an 
object in some other nib. This is one of the uses of the "responder 
chain". Under the hood, 

   [NSApplication sendAction:@[EMAIL PROTECTED]
(action:) to:nil from:aMenuItem]

gets called. Since NSApplication inherits from NSResponder, the code in 
NSResponder starts with the current responder, usually a view of a 
window, walking up the responder tree to the root, calling 
respondsToSelector: until it finds an object that responds to that 
message then it calls it. (I'm skipping some details here.)

5.) Notifications

Suppose you need something like delegation, but you expect more than one 
object to be interested. NSNotificationCenter lets you register that an 
object is interest in a notification, and objects call 
[NSNotificationCenter postNotification:...] to trigger all the observers.

For example at app shutdown, you might have multiple listeners for
NSApplicationWillTerminateNotification

Notification interacts with reference counting: if you registered for 
any notifications, you must explicitly unregister in your [dealloc], 
otherwise NSNotificationCenter will send notifications through a bad 
pointer. (If NSNotificationCenter retained all the observers, then none 
of them would ever get their reference count decremented to zero, so 
none would ever be dealloced)

I don't like Notifications because you can't step through them in the 
debugger. Instead, you search over the whole project for calls to 
addObserver:... with the correct name, search again for the methods 
referenced in those calls, set breakpoint on those methods, then 
continue. Then disable all of those breakpoints. What a pain!

6.) Key-Value Observing

Suppose it is a pain to go through your code adding 
-[postNotificationName:object:userInfo:] calls in many places. You can 
use Key-Value Observing to tell the system: whenever this setter is 
called in this object. Call my -[observeValueForKeyPath:(NSString 
*)keyPath ofObject:(id)object change:(NSDictionary *)change 
context:(void *)context] 


This is the ultimate "come from" statement. You are stepping along in 
the debugger, executing an innocuous setter, and suddenly some code on 
the other side of the program runs, without the debugger telling you 
about it.

There are fewer retain/release issues here: observers can't retain 
observees for the reasons I've previously described, but since dead 
objects don't change, your observeValueForKeyPath: won't get called on a 
dead object. You may crash, however, when the observer, in its dealloc, 
calls removeObserver:forKeyPath: (someone who knows more about this than 
me can let me know if it is mandatory to call 
removeObserver:forKeyPath:, or if the system will take care if it for 
you.)

Make sure you know about triggerChangeNotificationsForDependentKey: it 
is useful in real programs to make sure that all the observers of all 
the derived attributes actually get called.


7.) Conclusion

If one object must call methods in another, from tightest binding to 
loosest binding:

a. call a method in a member (i.e., there is a setter/getter pair that 
"owns" the other object.)

b. call a protocol method in a member (like above, but we don't care 
about the specific type, just that implements the protocol.)

c. call a method in a delegate, if it implements it.

d. post a notification (All the listeners will see it, in undefined 
order.)

e. As setters go about their business modifying the model, 
observeValueForKeyPath:... "magically" fire.

You as the programmer are expected to balance the issues: convenience 
versus explicitness.  As you go down this list you gain flexibility and 
power, but make you program more mysterious and harder for a novice to 
figure out.


I hope this puts things in perspective.
 




 4 Posts in Topic:
Help with Delegates and File's Owner
Cory <cory.imdieke@[EM  2008-04-18 20:42:46 
Re: Help with Delegates and File's Owner
David Phillip Oster <o  2008-04-19 11:44:30 
Re: Help with Delegates and File's Owner
Sherman Pendley <spamt  2008-04-19 16:12:17 
Re: Help with Delegates and File's Owner
Cory <cory.imdieke@[EM  2008-04-19 22:27:15 

Post A Reply:
  Go here to Signup

AddThis Feed Button


About - Advertising - Contact - Frequently Asked Questions - Privacy Policy - Terms of Use - Signup

Contact
localhost-V2008-12-19 Wed Jan 7 19:41:31 PST 2009.