A protocol is a list of method statement , anyone who conforms to it must or may implement it .
In most cases,a delegate's implementation relies on protocol,such as below:
#protocol VSActivateCouponDelegate <NSObject>
-(void)activateCouponSuccessWithActivateType:(ActivateType)type;
#end
My question is protocol's usage scenarios except implementing Delegate ?
For example, any interface that you want to keep generic in terms of not knowing the exact class that will be providing a specific role in some relationship. Delegate is one example of that but any relationship between two classes could use the same approach to abstraction.
Check out NSCopying, NSCoding etc. These are also protocols, but they are not used as delegates.
Let's look at NSCopying for example. If a class conforms to NSCopying, you know that you can call copy on any of its instances (and... copy it ), without even looking at the specific class, you can even pass instances as id<NSCopying> - this makes things more decoupled. For instance NSDictionary only accepts key values that are id<NSCopying>.
To summarize, protocols let you declare behavior without coupling it to a specific class. It doesn't always have to be delegates.
an example would be:
say you have an array of arbitrary objects of arbitrary types. now you want to make sure that all the objects at least have a certain function you can call on all of them to make them do something, then you can make all those objects conform to a protocol that has that method, thus making sure all the objects in that array have that certain functionality.
pseudo code of what that may look like:
#protocol MyProtocol {
- (void) doSomething;
}
//used somewhere
for(MyProtocol object in arrayOfUnknownObjects)
[object doSomething]; //dont know what object's type is but we know it has [doSomething] method
Related
Im trying to understand the high level implementation of protocols without delegates in Apple frameworks. When a subClass conforms to and implements a protocol method, how is that method called? Lets consider the NSCoder protocol methods (encodeWithCoder: and initWithCoder:) for instance.
Without delegates, could you provide any uses cases for protocols (other than achieving polymorphism? I see that some methods could be abstracted away from base classes and grouped into an interfaces but without any implementation (as mixins for instance), what is the significant use?
First, protocol methods are not special in any way. They, like every other Objective-C method, gets called by a message sent to an object. There's nothing special about that part of things. Protocols are basically just a hint to the compiler, though you can query whether an object conforms to one at runtime and make decisions based on that.
You can verify this by implementing a protocol method (or the entire protocol) without declaring that fact in a classes' interface, and call the function on an instance of that object after casting it to be id<YourProtocol>, and it will work.
You can (and sometimes should) call NSCoding methods yourself -- you may decide that you want to persist objects to the disk, and that this is the best way to do it.
NSCoding is actually a great example of why protocols are still useful even though they do not provide any implementation -- the implementation of initWithCoder: and encodeWithCoder: will be different for every class that implements them -- there is no sense in providing an implementation.
Building on that, consider the datasource property of a UICollectionView; as there is no multiple inheritance in Objective-C, it would be undesirable for the datasource to be a class itself, as that would prevent you from using a UIViewController as the data source, and force you to make a whole new class for that express purpose.
Protocols can also be used to implement multiple inheritance in a type safe way without redeclaring the interface of the giver in the inheritor. If the entire interface of the class being inherited from is a protocol, then the inheritor can simply conform to that protocol as well.
Objective-C does provide mixins in the form of Categories, which can implement protocols on existing classes.
For a full throated defense of protocols (in Swift), see the Protocol-Oriented Programming WWWDC 2015 talk.
Taking the example of the NSCoding Protocol, the two required methods in the protocol, basically implement the steps an object should perform to encode itself to be archived. It also implements the initWithCoder to recreate the object from the archive.
Lets say you create a custom object, only your object knows which properties it needs to archive.
When you call a method to archive your custom object, the method call ultimately flow to your encodeWithCoder or initWithCoder to take action specific to your class.
***** Updated ****
Looking at this with an example :
Lets say our data structure looks like this
someArray = [String,CustomObject,aDictionary]
When we want to archive someArray, we call the archiveRootObject method on it. Now inorder for someArray to archive itself, it needs all its contained items to inturn archive themselves. The Array simply instructs the sub items to archiver themselves calling the encodeWithCoder method on them.
By adopting and conforming to the NSCoding protocol, you are just confirming to the root array that Yes, I know how to archive and unarchive myself.
Hope this helps.
This has a sort of Responder Chain feel to it, but the difference there is, the responder chain is a defined operation on views and view controllers specifically.
Well, I need to pass along a method call through several unrelated classes, and being fairly new to Objective-C, i'm not sure if it would be a hack to define a protocol, and then implement that protocol on every class that the call needs to pass through.
For example...
ClassA is the delegate to ClassB.
ClassB is the delegate to ClassC
... hence the 'responder chain' feel.
Does this make sense for the code to pass along a call from C to B to A.
I assume at some point, when the chain gets too long, you'd probably recommend a notification technique instead, but I don't know what that recommended length might be.
#protocol DidSomething
-(void)userDidSomething:(NSString*)something
#end
ClassA <DidSomething>
-(void)userDidSomething:(NSString*)something
{
NSLog(#"The user did something %#",something);
}
ClassB <DidSomething>
-(void)userDidSomething:(NSString*)something
{
[self.delegate userDidSomething:something];
}
ClassC <DidSomething>
-(void)thatWasInteresting
{
[self.delegate userDidSomething:#"Cool"];
}
Nope. Nothing wrong with that. Save for the potential complexity.
You could define it as a protocol, if you want. Or you could define it as a common abstract superclass (if possible).
Protocols are generally the way to go these days and using #optional requires the use of a respondsToSelector: test (or conformsToProtocol:).
All in all, though, you should be very careful about the use of such a pattern. Specifically, it implies a lot about the architecture of your application and, thus, you want to make sure the architecture is sound.
Another alternative is using NSNotificationCenter to post NSNotifications. Object can add themselves as observers. Depending on your needs, this might be a good alternative to passing a message through a chain of delegate.
It is especially useful if more than one object needs to respond to a message.
Quick question about semantics :)
If I was writing a protocol, which is preferred:
// (a)
#protocol MyProtocol
#property (nonatomic, copy) NSSet *things;
#end
vs.
// (b)
#protocol MyProtocol
- (NSSet *)things;
- (void)setThings:(NSSet *)things;
#end
(a) is cleaner code but has the implication that implementing classes will have an ivar for things, which isn't the case in my project. Because of my use case, things cannot be KVO either. It also implies that the implementing class will copy things, which it's not doing in every case for me.
(b) is more accurate code (it's very explicit about what you can / can't do i.e. no KVO) but it's a little messier.
Any opinions?
I am amending my answer that (a) probably is not best for a protocol but best for a non-protocol interface.
I would go with the #property. How a property is implemented is an implementation detail and I never consider that from the outside.
Consider a v1 implementation where the property is only that. In v2 the internals are changed and either the setter or getter is made a method. Totally reasonable, one of the reasons that properties are good, they allow such changes, they hide the implementation details.
Also consider the opposite, in the next version where is is desired to remove the methods and replace them with a property. Again an implementation detail that a property in the first instance covers quite well.
Finally, in this case there is a copy attribute which provided explicit information of how a call with a mutable object will be handled, that is lost in the method implementation.
Protocols define messaging contracts [1]. They are not intended to store data. According to the Apple documentation you are only supposed to add properties to class extensions (you can add properties to categories but the compiler won't synthesize an ivar) [2]. Depending on what you are trying to do I would use one of the two following approaches to be consistent with the documented usage of the Objective-C language:
If you have the source code of the class (its one you created) then use a class extension.
If you do not have the source code sub-class the object.
That being said, if you really need to do it the other way use option (b). It is more corect and more correct is cleaner code!
Here is another question that deals with the same issue.
Good luck
I think case 'a' makes misinformation: class adopting protocol MyProtocol can follow not rules nonatomic and copy.
And for me it's very odd add properties inside protocols. It is going against paradigms of object oriented programming: delegates shold do some action, not provide informations.
So I advice you not use 'a' and 'b' cases, but to think again about yours programm architecture.
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!
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.
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! :)
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>
My question may seem strange, but i wanna to get this idea around Stackers' minds, in my work i just noticed that every protocol is conformed by a class all the time, i wondered about the possibility to make a simple object conforms to protocols too, and if not (and almost not ), why not ??
Appreciate your concern
There are two parts to protocol conformance:
the object must respond to the required messages in the protocol definition
the object must return YES when asked whether it conforms to the protocol
So, can we arrange for an instance of NSObject to satisfy those two conditions? Yes. In fact, there are at least two ways to do so. First, let's make all instances of NSObject conform to the protocol. What we do is to define the protocol methods in a category on NSObject, which solves the first part. Then we "swizzle" (which means using the class_replaceMethod() runtime function) -[NSObject conformsToProtocol:], returning YES for our interesting protocol.
Now let's imagine that you want to make a specific instance of NSObject conform to the protocol. This is slightly easier. First, create a subclass of NSObject that conforms to the protocol and implements the required methods; there's no need to override -conformsToProtocol: because the runtime library can see that this class conforms. Now, at runtime, take your NSObject instance and call object_setClass() to switch its class to your conforming subclass.
You can add protocols to classes at runtime, using the runtime function class_addProtocol(). However, doing so when the class does not implement all the methods of the protocol will likely lead to bad results.