-->

What exactly are protocols and delegates and how a

2019-01-13 16:38发布

问题:

I'm really confused about the concept of delegates and protocols. Are they equivalent of interfaces and adapter classes in Java? How do they work? None of the resources I've read were helpful so far. "Delegation is a simple and powerful pattern in which one object in a program acts on behalf of, or in coordination with, another object. The delegating object keeps a reference to the other object—the delegate—and at the appropriate time sends a message to it." I have no idea what this means. Can someone please explain what they are and give a simple example? Thanks in advance!

EDIT:

As far as I now understand,

1) delegates implement protocols (another name for interfaces)

2) object registers a delegate (that implements a protocol)

3) object can call protocol methods on the delegate

Therefore, a delegate is connecting the object with the protocol.

Please correct me if I'm wrong.

I still don't understand why the object itself can't implement a protocol? It could've been so much easier!

回答1:

Protocols are a way to specify a set of methods you want a class to implement if it wants to work with one of your classes. Delegates and Data Sources like UITableViewDelegate and UITableViewDataSource are protocols indeed.

You specify a protocol this way:

@protocol MyProtocol <NSObject>

- (void)aRequiredMethod;

@required
- (void)anotherRequiredMethod;

@optional
- (void)anOptionalMethod;

@end

Methods declared after the @required or before any other specifier are required and the classes that want to use your protocol need to implement all of them. You can also declare some optional methods by declaring them after the @optional specifier.

You then can specify that a class "conforms" to a protocol (implements the required methods) in the interface of the class:

@interface MyClass <MyProtocol>

@end

You usually keep a reference to an object conforming to a protocol using a property. For example, to keep track of a delegate:

@property (nonatomic, weak) id<MyProtocol> delegate;

At this point, in your code, you just have to call the method you want to call on the object that you're keeping reference of and that implements your protocol as you would with any other method:

[self.delegate aRequiredMethod];

To check whether an object conforms to a protocol you can call

[self.delegate conformsToProtocol:@protocol(MyProtocol)]

To check whether an object implements a method you can call

[self.delegate respondsToSelector:@selector(anOptionalMethod)]

For more information, check the Apple's guide Working With Protocols.



回答2:

A protocol which declared with the (@protocol syntax in Objective-C) is used the declare a set of methods that a class that "adopts" (declares that it will use this protocol) will implement. This means that you can specify in your code that, "you don't care which class is used so long as it implements a particular protocol". This can be done in Objective-C as follows:

id<MyProtocol> instanceOfClassThatImplementsMyProtocol;

If you state this in your code, then any class that "conforms" to the protocol MyProtocol can be used in the variable instanceOfClassThatImplementsMyProtocol. This means that the code that uses this variable knows that it can use whichever methods are defined in MyProtocol with this particular variable, regardless of what class it is. This is a great way of avoiding the inheritance design pattern, and avoids tight coupling.

Delegates are a use of the language feature of protocols. The delegation design pattern is a way of designing your code to use protocols where necessary. In the Cocoa frameworks, the delegate design pattern is used to specify an instance of a class which conforms to a particular protocol. This particular protocol specifies methods that the delegate class should implement to perform specific actions at given events. The class that uses the delegate knows that its delegate coforms to the protocol, so it knows that it can call the implemented methods at given times. This design pattern is a great way of decoupling the classes, because it makes it really easy to exchange one delegate instance for another - all the programmer has to do is ensure that the replacement instance or class conforms to the necessary protocol (i.e. it implements the methods specified in the protocol)!

Protocols and delegates are not restricted only to Objective-C and Mac/iOS development, but the Objective-C language and the Apple frameworks make heavy use of this awesome language feature and design pattern.

Edit:

Please find this Example. In the UIKit framework of Cocoa Touch, there is a UITextFieldDelegate protocol. This protocol defines a series of methods that classes which are delegates of a UITextField instance should implement. In other words, if you want to assign a delegate to a UITextField (using the delegate property), you'd better make sure that this class conforms to UITextFieldDelegate. In fact, because the delegate property of UITextField is defined as:

@property(nonatomic, assign) id<UITextFieldDelegate> delegate

Then, the compiler will give warnings if you assign a class to it that doesn't implement the protocol. This is really useful. You have to state that a class implements a protocol, and in saying that it does, you're letting other classes know that they can interact in a particular way with your class. So, if you assign an instance of MyTextFieldDelegateClass to the delegate property of UITextField, the UITextField knows that it can call some particular methods (related to text entry, selection etc.) of your MyTextFieldDelegateClass. It knows this because MyTextFieldDelegateClass has said that it will implement the UITextFieldDelegate protocol.

Ultimately, this all leads to much greater flexibility and adaptability in your project's code, which I'm sure you'll soon realise after using this technology! :)



回答3:

In it's simplest form a delegate is an object which receives messages from another object. And you do it all the time.

So say you had car object with an engine.

@interface car : NSObject

@property (nonatomic) id engine;

@end

So could forward a start message to the engine.

[_engine start];

The engine is acting as a delegate, you're just passing it a message.

Protocols make it more formal, and Xcode will check that you are conforming to the required or optional methods.

@property (nonatomic) id <engineDelegate> engine;

says that the engine object MUST contain the function start because in the the protocol definition it asked for it.

@protocol engineDelegate 
 - (void) start;
@optional
 - (double) fuelLevel;
@end

Why are delegates and protocols so cool? Well because the engine could be any number of different engines which you could use at runtime, it could be a jet engine, a combustion engine, a phasing modulating engine it doesn't matter, as long as it conforms to the protocol. And you tell Xcode that it does conform by adding the delegate to the class interface.

@interface timeWarpDrive : NSObject <engineDelegate>