可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I know a good bit of Objective-C and I'm working on a iPhone SDK book (coming from a Obj-C book that just did console programs). It attempted to explain delegates though it was rushed and didn't really understand what it was trying to convey. I'm a little confused on what they are and when you would use them.
Basically it said they are classes that take responsibility for doing certain things on behalf of another object.
Anyone care to elaborate?
Thanks!
回答1:
Think of delegates as inversion the direction of dependencies. In most frameworks the clients will inject the required dependencies into instances, usually in the constructor or by setters.
Cocoa does the reverse; instances instead request the data when and if it is needed.
There are four main types of delegate methods:
- Conditionally before - Signals something is about to happen, but the delegate may abort. Name always include the word Should.
Example: searchBar
Should
EndEditing:
.
- Unconditionally before - Signals something is about to happen. Name always include the word will.
Example: application
Will
Terminate:
.
- Unconditionally after - Signals something has happened. Name always include the word did.
Example: application
Did
FinishLaunching:
.
- Customizers - Request information for how to function. Name includes the information that is required.
Example tableView:
viewForHeaderInSection
:
.
All delegate methods always have their sender as one of the arguments. Any delegate method may have a return value that alters how the sender behaves.
回答2:
Let's say you want to present the user with an alert, and you want a method to run when the user touches one of the buttons. The problem is, how do you know what method to call, on which object, when someone touches a button?
In order for a class to be a delegate, you have to declare it as such. In the above example, lets say you have an ApplicationController object which controls the flow of your application. In the declaration, we would say
@interface ApplicationController : NSObject <UIAlertViewDelegate>
This tells the compiler that ApplicationController is going to implement some methods in the UIAlertViewDelegate protocol. We look that protocol up in our documentation, and see a list of methods. As we want to do something when a button is pressed, we see:
alertView:clickedButtonAtIndex:
- Sent to the delegate when the user clicks a button on an alert view. This method is optional.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
So, if we implement a method in ApplicationController called alertView:clickedButtonAtIndex
, create an ApplicationController object, and then set that object as the delegate of an alert we show, everything is set up. As soon as someone presses a button on the alert, the alertView:clickedButtonAtIndex
method will be called, passing in the alertView and the index of the button pressed.
This allows you to do whatever you want with that information. A simple case statement:
if( buttonIndex == 0 ) {
_myString = @"Pressed the button";
} else {
_myString = @"Pressed the other button";
}
The Objective-C reference docs are very, very good, and all the delegate protocols are pretty self explanatory.
回答3:
A good way to understand delegates is through example. One example is UITableView
(or NSTableView
, depending on whether we're talking iPhone or Mac OS). Either way, the table view has a delegate
and a dataSource
(both of which act as auxiliary objects to the receiver).
Instead of UITableView
handling the events when, for example, one of its rows is tapped by a user, it instead tells its delegate
"Hey! I've been tapped on this row and this section, do what you will!". Typically the delegate
is a Controller of some sort, which implements the correct method. So the table view (after checking to see if the delegate
actually has a definition for the method) sends a message like this:
[delegate tableView:self didSelectRowAtIndexPath:indexPath];
Since your Controller is the table's delegate, and it implements that method, it decides what to do. When the method completes (in this case it should just return void
), then execution continues on the table view.
Delegates are a concept. It's not a language feature of Objective-C. The delegate
member of UITableView is like any other object. Although, delegates typically are not retained, they are instead assigned (to avoid retain
cycles).
They are very handy when you get the hang of them. I suggest practicing with examples like TableViews (NSTableView
, like I said earlier, works in a similar way, just with different methods).
回答4:
A delegate (which means representative) is a class('s object) that wants to also represent (inherit from) another unrelated class. The delegate object is able to inherit from an otherwise unrelated class by "conforming to" (having some implementations for) the unrelated class's required protocol methods, which indicate to the foreign class that this object is now capable of volleying its most basic information appropriately.
You use inheritance when you want related classes to share methods. You use delegates when you want unrelated classes to share methods. The delegate approach lets an object from one class inherit methods from an otherwise unrelated class. The "delegate object", or "representative object", is the object that is inheriting from a foreign class; it is designated as a representative, a delegate, of that remote class, so that when you assign an object as a delegate to a class, you are giving it permission to represent that class also, even though it does not normally inherit from that class. (If it inherited from the class, then you wouldn't need to set it as a delegate of that class; it would already have access to the class's methods. But you want this unrelated object to inherit some methods from the class, representing that class, and returning some information back to its sender class, so you make it a delegate representative of that class even though it inherits from a different set of classes.) This essentially allows one unrelated class to inherit from another unrelated class, but with a minimum of complications to its basic line of inheritance.
You use the delegate system when you want an object to execute code from a separate class. For example, as described here, when you hit Enter in a text field, the text field doesn't really know what to do with that information. What it does is looks to its delegate object's class (such as the document's window controller or the document) and uses that class's relevant method which conforms to the text field's respective method found within its text field delegate protocol, something like textFieldShouldReturn. So in this case, you set the window controller or the document as the delegate of the text field, because the text field needs that class to represent the information it was given.
Class A needs a method from Class B, but Class A does not inherit from Class B. First, tell the compiler that Class A conforms to the Class B protocol:
@interface ClassA : NSObject <ClassBDelegateProtocol>
In the Apple Documentation, each class reference shows at the top, "Inherits from" and "Conforms to". For example, NSDocumentController
inherits from NSObject
and conforms to NSUserInterfaceValidations
, NSCoding
, and NSObject(NSObject)
. The conformance to NSCoding
is from the interface declaration in NSDocumentController.h
@interface NSDocumentController : NSObject <NSCoding>
and to NSUserInterfaceValidations
from the method declaration in NSDocumentController.h
-(BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item;
along with the #import
#import <AppKit/NSUserInterfaceValidation.h>
So whereas NSDocumentController
inherits from NSObject
, it wants some help also from NSCoding
and NSUserInterfaceValidation
. And it gets help from these foreign classes by conforming to their protocol methods, defining itself as conforming to those methods, and importing any necessary header files to use those methods.
回答5:
Take a look at my tutorial on the delegate design pattern here: http://www.jonmsterling.com/blog/?p=74. I hope that helps.
回答6:
You are not alone, I am still learning this myself. I think its best if I try to explain it in words instead of code. There is a protocol which hold a certain method or action you want to accomplish. The delegate takes method from the protocol so are able to use it to facilitate an action or method. I found this article to be very helpful
http://rypress.com/tutorials/objective-c/protocols. Hope this helps.