Re: new to Cocoa/Objective-c: many points of confusion
Re: new to Cocoa/Objective-c: many points of confusion
- Subject: Re: new to Cocoa/Objective-c: many points of confusion
- From: Andy Lee <email@hidden>
- Date: Sun, 03 Feb 2013 07:47:56 -0800
Hi Alex,
Lots of basic topics here that I love to talk about. I'll just focus on delegates, at least for now.
On Jan 21, 2013, at 10:10 PM, Alex Hall <email@hidden> wrote:
> *delegates: my understanding is that these take the place of subclasses (though why this is useful is beyond me), overriding methods they are designed to handle rather than letting the base class take those methods. However, I not only don't see why this is so great, but I don't understand the syntax used to declare them or attach them to other classes so the delegates' methods get called when any of those methods are called on the object to which the delegate is attached. Every example I have found seems to indicate they are used only for GUIs, but Apples docs say that they are a much more general-purpose system?
>
> *Speaking of delegates, I don't follow the syntax used to set them up. Every example seems to love to use views or other UI examples, which would be fine if I could follow that, but I'm not that advanced yet. A more basic, even if not-so-useful-in-reality, example would be very much appreciated.
Comparing delegation to subclassing is exactly the right question. In both cases you'd like to change some aspect of how an object behaves. To do this with a subclass, as you're used to, you override some method and put the desired behavior there. Sometimes that method is one you will call yourself. Sometimes it is one that you'll *never* call yourself, but gets called for you in the course of the object's lifetime. It depends on the method, in Cocoa as in Java.
To use delegation, you put the special behavior in a method of a *different* object which you designate as the first object's delegate. To connect the delegate in code (as opposed to Interface Builder) the method is almost always called setDelegate:. You're just setting an instance variable using a setter method, just as you would do in Java.
You typically don't call a delegate method directly. Delegate methods are typically called by the object itself, at various points in its lifetime. Often they're called just before or after the object does something, hence the "willDoSomething" and "didDoSomething" pattern in many delegate method names.
A simple non-visual example that might help is is NSSound, which has just one delegate method called sound:didFinishPlaying:. Here's a quick example of creating an instance of NSSound and giving it a delegate.
* In Xcode, create a new project of type "Cocoa application".
* In AppDelegate.m, add these lines to the applicationDidFinishLaunching: method that has been pre-supplied for you.
NSSound *sound = [NSSound soundNamed:@"Tink"];
[sound setDelegate:self];
[sound play];
* In the same file add the following method to the AppDelegate class:
- (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)finishedPlaying
{
NSLog(@"sound finished");
}
Run the app. (You'll get a compiler warning which you can ignore for now.) You should hear a "Tink" sound (it's one of the built-in sounds in Cocoa), and in the Xcode Console pane you should see the words "sound finished".
So, why would you do things this way instead of subclassing NSSound and overriding the "play" method?
* Separation of concerns. Cocoa is big on separation of concerns. Suppose, instead of simply logging a message, you wanted to do some things in the UI when the sound finishes playing. Maybe you want to change a text field to say "The sound finished playing!" Maybe your UI has a Play/Stop button that shows different icons when the sound is playing and when it's not. It doesn't make sense for an NSSound subclass to know about user interface. You'd put all that behavior in a delegate object that *does* know about user interface, and point the NSSound to that delegate. (The delegate would almost certainly be a "Controller" in the MVC paradigm, which Cocoa is very big on.)
* Delegates are inherited by subclasses. It's been said that delegation means you don't have to subclass, but it happens to provide a benefit when you *do* subclass. Suppose there were three subclasses of NSSound, any of which might get used (unpredictably) at runtime. With delegation, you're able to specify this custom behavior regardless of which subclass gets used. You can add more subclasses and they'll inherit this delegation ability as well.
Cocoa delegate methods follow well-defined conventions. For example, notice the "did" in "sound:didFinishPlaying:". As I mentioned, "did" and "will" are commonly used in delegate method names.
Also note that the first argument to sound:didFinishPlaying: is an NSSound. All proper Cocoa delegate methods are structured this way. There may be cases where your delegate method cares *which* sound object is doing the delegation. For example, you might want to print the name of the sound by modifying the delegate method like this:
- (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)finishedPlaying
{
NSLog(@"finished playing the sound named %@", [sound name]);
}
I didn't remember offhand that NSSound takes a delegate. I found it using my documentation browser, AppKiDo (http://appkido.com). It's an old app but it still has its uses. One feature I added was specifically to help people learn about delegates. There is a radio button in the drawer on the left that lets you list "Classes with delegates". You can skim the list and look at their delegate methods and get a general idea of what they're for, and the naming conventions for them.
I've never considered how accessible AppKiDo is, so I apologize if it turns out to be unusable for you. I'll add accessibility to my list of long-overdue improvements.
HTH,
--Andy
>
> *Outlets: I have a basic idea that these are a way of sending messages from object to object, a bit like listeners. However, I don't really understand the syntax used to make them. Moreover, I always see them used in GUIs, but Xcode's Interface Builder won't let Voiceover users make connections, so I can't proceed with Apple's tutorials on this topic. Somehow, these connections are outlets, or are related to outlets, or some connections are outlets, or something... Anyway, as I can't make the connections to get an idea of how they work, I'm trying to follow others' examples which I don't get as they use code I didn't write and that makes no sense to my newbie brain. So, what exactly is an outlet and how and why would I set one up? Again, a very basic code example would really help here.
>
> *Every so often I'll see a class between less- and greater-than signs when an example talks about a delegate, but I don't know what this is for. What does it mean to put these symbols around a class (or maybe they are around an object?)?
>
> *I've seen sample code that seems to go against everything I know about method calls:
> -(IBAction) someObject:(id)inSender;
> Huh? Is the (IBAction) casting, or a method call, or what (I understand what IBAction is, but not why it is where it is and in parentheses)? I know why the "id" is there, so this action will work with any UI element, but why the colon? What is inSender doing there, hanging out at the end of the line? How does the method (in the m file) have any idea what inSender is as it appears to not be an argument? Why does it need inSender if it already has the id argument?
>
> *What is a property? I see these used a lot, but I'm not clear on what they are compared to, say, class-level variables or methods. The statement I'm talking about is the "@property" statement.
>
> *I know that using the @synthesize statement auto-generates getters and setters, but no one ever talks about how to use them once they are set up. That is, what is the syntax for these generated methods? I assume it is "get" and "set", cammel-cased with the variable being synthesized (and with a single parameter matching the variable type in the case of the setter) but I want to be sure.
>
> Thanks in advance for any information. Oh, and yes, I have already researched all this thoroughly, having spent the last couple days reading every blog, article, apple doc, and forum I can find, but the above seem to be sticking points for some reason. I have no idea why I can't seem to get past these, but several concepts seem to be so important and oft-used that I am hopeful I will be able to move forward much more smoothly once I have them under my belt.
>
>
> Have a great day,
> Alex (msg sent from Mac Mini)
> email@hidden
>
>
> _______________________________________________
>
> 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
_______________________________________________
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