I have a base class SLBaseViewController which is a subclass of UIViewController and want all its subclasses to conform to protocol:
#protocol SLLocalizable <NSObject>
- (void)localize;
#end
The problem is that I don't need SLBaseViewController to conform to protocol itself, but I need compiler to warn me if a subclass doesn't conform.
What I have tried:
Define base class like this:
#interface SLBaseViewController : UIViewController <SLLocalizable>
In this case compiler tells me that SLBaseViewController does not implement localize method.
Make localize optional.
Compiler keeps silence. But that's not what I need.
Make each of subclasses conform to protocol itself. That seems to be a right way, but I have more than 50 subclasses and it's a long way.
Is there a simple way to reach my goal?
You can't specify that the subclasses implement any protocol other than to specify it in the subclass itself.
Search for the subclasses to edit them (rather than trying to remember each). A reflex search would be able to find subclasses which don't give the protocol name.
As a safety check, make the superclass throw an exception if it's called so you know when you missed something. Obviously this only works during testing.
If this makes you paranoid, you could try writing a unit test which gets all the subclasses and calls localize on them.
In what case would you need all subclasses to implement something, but don't need the common superclass to implement it?
If it is that SLBaseViewController is an abstract class that is not meant to be instantiated directly, you can simply have it implement -localize, and in the body throw an exception. Or, you can simply ignore the warning (it is just a warning after all).
Related
I have something like this:
#protocol MyProtocol <NSObject>
- (void)oneMethod;
#end
.
#interface BaseClassWithProtocol : NSObject <MyProtocol>
#end
.
#interface ChildClassWithProtocol : BaseClassWithProtocol
#end
BaseClassWithProtocol has implemented oneMethod, and I want to show warning if ChildClassWithProtocol doesn't call super in its oneMethod implementation.
But I don't know where should I write __attribute__((objc_requires_super)).
Writing it in protocol is not supported while redefining oneMethod in .h looks stupid.
So is there any standard way which can deal with the problem?
The requirement to call super is imposed by BaseClassWithProtocol. It's not part of the protocol. Surely, some class could implement MyProtocol however it wants without that requirement being imposed. That's the nature of protocols. They impose interface, not implementation.
So, redeclaring the method in BaseClassWithProtocol with the attribute seems perfectly sensible to me. Not sure why it "looks stupid".
Protocols aren't meant to give warnings for your diverse implementations. They only warn you whether you agree to include the required methods in your implementation or not. But how you implement the methods, that's up-to your Base class that adopts the protocol. That is, you should have your necessary functionalities in your .h or .m files.
Consider this way:
You have a method in your protocol where you want to have a warning for the super calls. Now you adopt the protocol in a class which is the sub-class of NSObject. But the NSObject class doesn't conform to the protocol you are defining. Would you now supposed to get the warning for your class? According to your requirements, you should get that warning. But this isn't the case. You would practically never get that warning by this procedure.
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
I have a class in my iOS app project that conforms to a certain protocol like this:
#interface MyViewController : UIViewController <aProtocol>
And at some time in the app I want this certain class to stop conforming to this very protocol. And then bring it back again.
Is there any way in obj-c where a class has some optional protocols? How is this controlled?
You cannot remove a protocol from the conforming class and bring it back again later. But you can always decide right at the design time whether the protocol has to be optional or required with the help of #optional and #required keywords. If you are thinking about using a definite protocol method in need, you can try delegation design pattern. The concerned delegate object may conform to the required protocol. And the delegating object may use this delegate in need.
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.