PDA

View Full Version : Confusion with "Helper Objects" in Cocoa...




Littleodie914
Jul 27, 2006, 09:28 AM
Hey guys, I'm diligently going through Aaron Hillegass' book, and am stuck on Chapter 5, Helper Objects.

What I understand is that a lot of classes in Cocoa have an instance variable 'delegate' that points to the helper object. An example it gave was having the helper object tell the tableView how many rows to display. Also, it says that NSSpeechSynthesizer has a delegate method didFinishSpeaking:.

This kinda makes sense to me, but I guess the question I have, is why deal with helper objects at all? Why can't the NSSpeechSynthesizer class have an instance method isFinishedSpeaking that returns a boolean? What's with the middle man? Thanks! :D



robbieduncan
Jul 27, 2006, 10:06 AM
The instance method isFinishedSpeaking would have to be polled to check when the current speach was finished then the action you want to do on completion performed. This is really inefficient.

The delegate method will be called when the speach is completed which is very effecient.

There is no middle man. You only need one object of your own either way.

kpua
Jul 27, 2006, 10:13 AM
Suppose you wanted to do something as soon as NSSpeechSynthesizer finished speaking. If you use the -(BOOL)isFinishedSpeaking you mentioned, you would be forced to poll NSSpeechSynthesizer to find out when it was done, blocking an entire thread and wasting CPU time. However, NSSpeechSynthesizer knows exactly the moment that it finishes speaking, and by providing the delegate method, it prevents the necessity of polling by calling -didFinishSpeaking.

Also, with the example of the NSTableView dataSource (which isn't quite the same as a delegate... there is both a dataSource and a delegate ivar within NSTableView), without the dataSource, the only other obvious way to add information would be through methods like setNumberOfRows:, setValue:column:row: and so on. However, this breaks the MVC model a bit because the NSTableView is forced to contain the data that it displays. The more appropriate thing to do is have a dataSource that is either a controller (to filter data from one or several models) or a model (to display all of that models data).

Littleodie914
Jul 27, 2006, 10:25 AM
Okay guys, now I see the difference... So if the object were to have an instance method that could be executed and would return a boolean, you would have to do this every time you wanted to check. The helper object will execute some bit of code at the exact time when the "thing" happens. (speechSynth stops speaking, etc.)

Makes much more sense now, thanks! :)

slooksterPSV
Jul 27, 2006, 06:16 PM
So let me get this right:
A delegate is a method you implement when a certain action either finishes executing or does something at a certain point that is called automatically right?
E.g. if I have the speech synthesizer class defined and that when the clip finishes playing (whatever words I typed in or that) it automatically calls didFinishSpeaking - so the speech synthesizer, when the clip finishes playing, it delegates didFinishSpeaking to execute what it needs to do right?

Would this be the same with iTunes? - songDidFinishPlaying, then it would test if there is another song to play and play that right?
So now if I have a progress bar can I set its delegate method to isFinishedProcessing and have it execute some more commands err.. set another objects as a delegate of another object?

Littleodie914
Jul 27, 2006, 07:59 PM
So let me get this right:
A delegate is a method you implement when a certain action either finishes executing or does something at a certain point that is called automatically right?
E.g. if I have the speech synthesizer class defined and that when the clip finishes playing (whatever words I typed in or that) it automatically calls didFinishSpeaking - so the speech synthesizer, when the clip finishes playing, it delegates didFinishSpeaking to execute what it needs to do right?

Would this be the same with iTunes? - songDidFinishPlaying, then it would test if there is another song to play and play that right?
So now if I have a progress bar can I set its delegate method to isFinishedProcessing and have it execute some more commands err.. set another objects as a delegate of another object?First paragraph is dead on. As for the iTunes thing, I don't know much about the methods related to it or anything like that, but your statement about the progress bar has me excited... I've always wondered how people make those work. :D

robbieduncan
Jul 28, 2006, 12:49 AM
A delegate is an object, not a method. Objects which use delegates normally have an informal protocol that defines the set of methods that the delegate object can implement.

I have never seen the ability to be the delegate to an external program as you describe. You provide delegates for objects within your own program.

Progress bars don't work like that at all. A progress bar delegate would be used to keep your object informed about progress bar events or customise the progress bar behaviour.

Note this initial question included some examples that are not delegate objects, in particular the discuss about table view included some data source methods. The table view data source does not have to be the same as the table view delegate.

I suggest you read this (http://www.stepwise.com/Articles/Technical/2000-03-03.01.html).

caveman_uk
Jul 28, 2006, 02:46 AM
I have never seen the ability to be the delegate to an external program as you describe.
I guess you could do it using distributed objects but I don't think I've ever seen anyone do it.

Littleodie914
Jul 28, 2006, 06:00 AM
Hey guys, I hate to hijack my own thread just a tad, but I'm going to assume that I have some OP authority and do so anyway. :) :D

I made it through Chapter 5, and almost all of the way through Chapter 6! I'm just stuck on the challenge at the very end. It's a bindings program, in which the challenge is to use a key path in IB to control the sorting of a Name column. In the actual tutorial/walkthrough, the program is initially designed to sort the Names using the Model Key Path "personName". The new desired method of sorting is by the length of the NSString that the dataSource is providing.

He says "(Hint: Strings have a length method.)", but that didn't really help me at all, as I've read through his page on key paths at least 100 times, and I swear it doesn't once describe how to implement class methods. I tried personName.length, length.personName, @personName.length, and everything else you could think of. Help a wee coder out! Again, thanks for all your generous help so far, I really appreciate it. :)

slooksterPSV
Jul 28, 2006, 09:47 AM
Hey guys, I hate to hijack my own thread just a tad, but I'm going to assume that I have some OP authority and do so anyway. :) :D

I made it through Chapter 5, and almost all of the way through Chapter 6! I'm just stuck on the challenge at the very end. It's a bindings program, in which the challenge is to use a key path in IB to control the sorting of a Name column. In the actual tutorial/walkthrough, the program is initially designed to sort the Names using the Model Key Path "personName". The new desired method of sorting is by the length of the NSString that the dataSource is providing.

He says "(Hint: Strings have a length method.)", but that didn't really help me at all, as I've read through his page on key paths at least 100 times, and I swear it doesn't once describe how to implement class methods. I tried personName.length, length.personName, @personName.length, and everything else you could think of. Help a wee coder out! Again, thanks for all your generous help so far, I really appreciate it. :)

int length = [personName length];

Littleodie914
Jul 28, 2006, 10:17 AM
int length = [personName length];Well sure, I know how to get the length of the personName string, but I just can't figure out how to sort the column according to that value. :(

caveman_uk
Jul 28, 2006, 10:27 AM
How about using an NSSortDescriptor (which you can bind to the tableview) and a custom comparison method?

Littleodie914
Jul 28, 2006, 10:27 AM
Alrighty, got it! I found a solution online...

It turns out I almost had it with my previous efforts, changing the Sort Key in IB under the Attributes of the column from personName to personName.length, but I kept getting errors. Turns out you also have to change the Sort Selector from caseInsensitiveCompare: to compare:. Does anybody know why this is? I mean it seems since it's sorting by length, it shouldn't matter whether it pays attention to the case or not. Thanks for all your replies! :)

robbieduncan
Jul 31, 2006, 07:04 AM
Alrighty, got it! I found a solution online...

It turns out I almost had it with my previous efforts, changing the Sort Key in IB under the Attributes of the column from personName to personName.length, but I kept getting errors. Turns out you also have to change the Sort Selector from caseInsensitiveCompare: to compare:. Does anybody know why this is? I mean it seems since it's sorting by length, it shouldn't matter whether it pays attention to the case or not. Thanks for all your replies! :)

caseInsensitiveCompare: will work on strings (NSStrings or subclasses of). compare: works on more general objects (anthing that implements the compare: method) so it will work with NSNumbers.

If you think about it this makes sense. Is the length of a string uppercase or lowercase? (clearly the answer is neither)

Krevnik
Jul 31, 2006, 09:37 AM
caseInsensitiveCompare: will work on strings (NSStrings or subclasses of). compare: works on more general objects (anthing that implements the compare: method) so it will work with NSNumbers.

If you think about it this makes sense. Is the length of a string uppercase or lowercase? (clearly the answer is neither)As a final comment to the topic of delegates. The use of delegates is caused by the Model-View-Controller concept. You don't want your view (such as a table/progress bar) to be the one executing code that defines its specific behavior (subclassing). Instead, you want to have a controller/delegate handle the specific behavior, that can be tested and confirmed without the control in place (unit testing).