I want to define a protocol and create an easy, standard way to grab a 'default', shared implementation of said protocol - singleton style. Cocoa adhere's to the following pattern:
[NSUserDefaults standardUserDefaults]
[NSNotificationCenter defaultCenter]
but in both cases, they have #interfaces at the bottom of the object hierarchy. I'm struggling with how to do this using #protocols. I can obviously create a class that has empty or simple method implementations - but in reality, what I want is a #protocol at the bottom of the hierarchy. I've tried something like:
#protocol ConfigurationManager <NSObject>
//...
#interface ConfigurationManagerFactory : NSObject
+ (id<ConfigurationManager>)sharedConfiguration;
#end
// ...
id<ConfigurationManger> config = [ConfigurationManagerFactory sharedConfiguration];
[config ...];
and it works - but I'm always having to explain how to use this and why I did it this way. Is there a way to conform to Cocoa's syntax (calling convention) while still leveraging the value of #protocols?
As an aside, is there a reason why I wouldn't want to use #protocols like this? The implementing #interface can still leverage categories and alternate implementations, etc - just like how instantiating an NSString usually leaves you with a class extending NSString.
Here's an idea: create your protocol and a class with the same name with a factory method that returns you the default implementation of the protocol:
#protocol ConfigurationManager <NSObject> ...
#interface ConfigurationManager : NSObject <ConfigurationManager>
+(ConfigurationManager *) defaultConfigurationManager;
...
Other specialized implementations can then inherit from your base class.
The whole point of a protocol is that it specifies an interface without providing an implementation. If you want a default implementation, provide a class that implements your protocol, much as the NSObject class implements the NSObject protocol. Then clients can either subclass the class that you provide, or instantiate the class you provide and use the resulting object's implementation, as with your config object.
Related
Ok, there are several questions with "Protocol" and "Inheritance" but I can't really find the answer to my question. I have a class with a protocol. For example:
#class SomeClass;
#protocol SomeDelegate <NSObject>
#optional
-(void) someMethod;
#end
#interface SomeClass : NSObject
{
id<SomeDelegate> delegate;
}
#property id<SomeDelegate> delegate;
-(void) thisDoesStuff;
#end
Then I have a different class whose object will be a delegate of a SomeClass object:
#interface DiffClass: SomeClass<SomeDelegate>
// This method will conform to the one specified on the protocol
-(void) someMethod;
#end
My question is, does DiffClass inherit from SomeClass? I'm considering the syntax in Objective C for inheritance:
#interface ClassA : SuperClassOfClassA
Where, in the above, ClassA inherits from SuperClassOfClassA.
Additionally, in Objective C, is it possible to inherit from one class and adopt a protocol from a different class? I guess what I'm trying to get at is if it's possible that two objects are able to communicate to each other through delegates without having to inherit from that protocol's class (I hope I'm making sense).
Thanks in advance!
In practice, your code would be very strange.
First, you don't have a class with a protocol. You have a protocol named SomeDelegate. Then you have a class SomeClass, which is unrelated to the protocol. Well, it has an instance variable that supports SomeDelegate, but that has nothing to do with the protocol.
Then you create a class that is both a subclass of SomeClass, and supports the SomeDelegate protocol. That's unusual. I mean DiffClass both supports the protocol itself, and has a delegate supporting the protocol. That's a bit strange.
Nevertheless, DiffClass is a subclass of SomeClass, and you promised that it supports the protocol SomeDelegate, so that's fine.
But really: A protocol doesn't belong to a class. I don't know what made you think that, but you have to remove that from your brain immediately. A protocol is a totally different thing and totally independent from a class. It's a set of requirements that any class may or may not fulfil. It exists independent of any class. Because a protocol is a set of requirements, a class can support that protocol by claiming it does (adding ) and by adding the required methods.
To answer your first question, DiffClass does inherit from SomeClass as you have it written. But it doesn't need to inherit from SomeClass. I'll be a bit more thorough below.
A protocol is a declaration of methods (and properties) that a class adopts. It does not have to be related to a class, although it often is for the delegation pattern.
For example, you could have a header that just declares a protocol. Let's call the file NewProtocol.h
#protocol NewProtocol<NSObject>
#optional
- (void)newMethod;
#end
Then any class can adopt that protocol. With your example above, this could be DiffClass. You do not need to declare the methods from NewProtocol again in the class interface.
// You would need to import NewProtocol.h
// Note that this does NOT inherit from SomeClass.
#interface DiffClass : NSObject<NewProtocol>
#end
Then the implementation of DiffClass would need to provide the declared protocol methods.
#implementation DiffClass
- (void)newMethod {
// Do stuff.
}
#end
Then SomeClass could have a property for the declared protocol above.
#interface SomeClass : NSObject
// Often you will want weak for delegates as they can cause retain cycles otherwise.
#property(nonatomic, weak) id<NewProtocol> thingThatImplementsNewProtocol;
-(void) thisDoesStuff;
#end
DiffClass does now NOT inherit from SomeClass but can be used to communicate with SomeClass. You could declare a second protocol that SomeClass adopts and a property on DiffClass to have two way communication.
Often the protocol are declared in the same header file as a class for simplicity because they are intended as delegates for specific objects.
Answer to the question 1: with the statement
#interface DiffClass: SomeClass<SomeDelegate>
The DiffClass inherits from SomeClass and also conforms the protocol(interface) SomeDelegate.
Answer to the question 2: In Objc you can inherit only from one parent class (multiple inheritance wont be supported) but you can conform as many as protocols (interfaces) you want.
Lets take and example of an drawing App. Shape is a parent class and RectangleShape, LineSahpe, TextShape, CircleShape are the children from Shape class. All four children are inheriting from their parent Shape. But you need to move the shape except LineShape. There you can have protocol (interface) as Movable. That you can do so.
#protocol Movable <NSObject>
#end
#interface Shape : NSObject
#end
#interface RectangleShape : Shape <Movable>
#end
#interface LineSahpe : Shape // cannot be moved, just for an example.
#end
#interface TextShape : Shape <Movable>
#end
#interface CircleShape : Shape <Movable>
#end
You can have a method for the protocol like this to move all Shaped which are conforming Movable protocol (interface).
- (void)move:(id <Movable>)movableShape {
}
You can implement a communication instead of moving shapes. Protocols are really useful during advanced programming.
Hope it will help you... please feedback me.
Is there a way to tell the compiler that a non-imported class (i.e. forward declaration) adheres to a protocol?
In the example below I want to call a method foo on the class ForwardClass. The class adheres to the MyProtocol protocol, but the compiler won't know that since forward declaration is used.
#protocol MyProtocol <NSObject>
+ (void) foo;
#end
#class ForwardClass; // <-- Forward declaration
#implementation MyClass
- (void) bar
{
[ForwardClass foo]; // <-- This doesn't work!
}
What I was hoping for was to either apply the protocol while declaring the class like so:
#class ForwardClass <MyProtocol>
or to somehow use the protocol while calling the method like so:
[ForwardClass<MyProtocol> foo];
This is not really a big issue since I could just import the class straight away, but it would be nice if it worked since I would only have to import the protocol, and not the whole class.
No. Forward declarations are for situations where you need to know the the class type but don't need to know about its specific implementation (properties and methods for example). In your case you do care about the methods it implements so you need to bring in the header for for ForwardClass.
You could do
Class x = NSClassFromString(#"ForwardClass");
[x foo];
but it is not as pretty
I have several subclasses of UIViewController that I want to use a single category to give them all a couple of methods. The thing is I only want my classes not the base UIViewController to have that categories methods.
Say I have:
PanelAViewController
PanelBViewController
...
That I want to implement and respond to a class:
PanelAnimations
-(void)animateIn;
-(void)animateOut;
I could use a protocol and insert the methods each time but they use the same methods and values, so wouldn't a category suit?
I am just not sure how to define the category for these custom classes.
Why you didn't consider subclassing, instead of using categories or protocols? Here here you can simply create an AbstractViewController class (which heritates from UIViewController) that defines the panel animations methods, and then derive your own concrete controllers (PanelAViewController, PanelBViewController, etc.) from the abstract one.
The abstract class will define the methods and eventually some stubs in the implementation (is up to you if you want that PanelA and PanelB should call super or not). This depends on the abstraction degree you want to give to the abstract class. See the code example below.
Sometimes it is not clear if it is better to use a protocol or subclass or delegate mechanism. Most of the times the boundary is not clear and the final decision is more dependent on the programmer preference than a "codified" architectural rule. Typically you use protocol when you want different objects to have a common behavior for certain tasks (e.g.: you have a complex set of entities and one of these entities should be used as a map annotation: in such case you must simply provide this specific entity the MKAnnotation protocol compatibility); delegate is mostly used when you want to extend a class without subclassing it or without given the final user the possibility to subclass it. In your case I think subclassing is the most appropriate choice as all classes are strictly part of the same class hierarchy, they share a common code (or common interface) and provide each a specialized implementation.
//
// AbstractViewController.h
//
#import
#interface AbstractViewController : UIViewController
-(void)doAnimate;
-(void)didAnimate;
#end
//
// AbstractViewController.m
//
#import "AbstractViewController.h"
#interface AbstractViewController ()
#end
#implementation AbstractViewController
-(void)doAnimate {
NSLog(#"Abstract do animate");
}
-(void)didAnimate {
NSLog(#"Abstract did animate");
}
//
// ConcreteViewController.h
//
#import "AbstractViewController.h"
#interface ConcreteViewController : AbstractViewController
#end
//
// ConcreteViewController.m
//
#import "ConcreteViewController.h"
#interface ConcreteViewController ()
#end
#implementation ConcreteViewController
-(void)doAnimate {
[super doAnimate];
NSLog(#"Subclass do animate");
}
Seems like your best bet would be to derive a custom class from UIViewController, call it say "MyUIViewControllerBase". Add your custom methods to that class, then derive the rest of your view controllers from it. No category needed and it solves your problem.
Suppose you have control over all your custom ViewControllers, the easiest way would be creating a subclass of NSViewController - like MyViewController - and subclass every other of your own ViewControllers from it. This way you would not even have to write a category for them. You could simply implement your wanted features within the MyViewController.
NSViewController
|
MyViewController -- implement your shared methods here
/ \
MyViewControllerA MyViewControllerB
I am trying to learn, how to implement delegation pattern in objective C. But the discussion almost exclusively concentrates on the adoption of protocols and then implementing the delegate methods that come with particular protocol - or - the delegation principle alone - or protocols alone.
What I am unable to find, is a easy to understand material about how to write a class that will serve as a delegator. By that I mean the class, which the message of some event will come from and which will provide the protocol for receiving that message - kind of 2in1 description. (protocols and delegation).
For the purpose of my learning, I'd like to go along the following trivial example, using an iPhone, a Cocoa touch application and Xcode4.2, using ARC, no Storyboard or NIBs.
Let's have a class with name "Delegator", which is a subclass of NSObject. The Delegator class has NSString instance variable named "report" and adopts the UIAccelerometerDelegate protocol.In the Delegator implementation, I will implement the the delegate method
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
This delegate method will create a NSString #"myReport" and store it in the report variable anytime there is an accelerometer event. Further, I want to have a second class named ReportsStorage (a subclass of NSobject), which can store some Nsstring (report) in its instance variable called latestReport.
So far so good.
Now lets get back to theDelegator Class. I'd like to implement a protocol in Delegator named ReportsDelegate which will notify the class that adopts it (the ReportsStorage class), that a report was generated and will pass this report through the delegate method, which should be (I believe) something like this
-(void)delegator:(Delegator *)delegator didCreateNewReport:(NSString *)report;
Can you please provide the code for Delegator Class (incl. the "delegate" property), that will achieve this, with a description what each line of code means?
Thanks in advance, EarlGrey
You'll need to declare the delegate property as an id<ReportsDelegate> type. That is, any object type (id) conforming to the ReportsDelegate protocol (<ReportsDelegate>). Then, if the delegate method is considered optional, check if the delegate responds to that selector before calling it. (respondsToSelector:).
Like so:
Delegator.h
#import <Foundation/Foundation.h>
// Provide a forward declaration of the "Delegator" class, so that we can use
// the class name in the protocol declaration.
#class Delegator;
// Declare a new protocol named ReportsDelegate, with a single optional method.
// This protocol conforms to the <NSObject> protocol
#protocol ReportsDelegate <NSObject>
#optional
-(void)delegator:(Delegator *)delegator didCreateNewReport:(NSString *)report;
#end
// Declare the actual Delegator class, which has a single property called 'delegate'
// The 'delegate' property is of any object type, so long as it conforms to the
// 'ReportsDelegate' protocol
#interface Delegator : NSObject
#property (weak) id<ReportsDelegate> delegate;
#end
Delegator.m
#import "Delegator.h"
#implementation Delegator
#synthesize delegate;
// Override -init, etc. as needed here.
- (void)generateNewReportWithData:(NSDictionary *)someData {
// Obviously, your report generation is likely more complex than this.
// But for purposes of an example, this works.
NSString *theNewReport = [someData description];
// Since our delegate method is declared as optional, check whether the delegate
// implements it before blindly calling the method.
if ([self.delegate respondsToSelector:#selector(delegator:didCreateNewReport:)]) {
[self.delegate delegator:self didCreateNewReport:theNewReport];
}
}
#end
In objective-c it is possible to add a #dynamic to a property.
Is this also possible for normal instance methods?
EDIT
I think i wasn't clear enough.
I want to do the following:
#interface MyClass
#property (retain) NSObject *somePropertyObject;
- (void) myMethod;
#end
#implementation MyClass
#dynamic somePropertyObject;
//Make myMethod dynamic. I do not want to implement it. Like C++ Virtual
#end
If you mean "How can I declare a method, but not provide a definition which I will subsequently provide at runtime?" Then it's easy, just use a category. Like this:
#interface MyObject : NSObject
// Methods I'll define
- (void)doFoo;
#end
#interface MyObject (DynamicallyProvidedMethods)
// Methods I won't
- (void)myDynamicMethod;
#end
#implementation MyObject
// Methods I'll define
- (void)doFoo
{
}
#end
The compiler will not complain, however if you call -myDynamicMethod at runtime, unless you have provided an implementation for it somehow, it will crash with "unrecognized selector." You can, of course, test for that at runtime by calling respondsToSelector:.
Relatedly, if you're looking to do a near-equivalent of a base class pure virtual method, I would recommend providing an empty implementation that asserts when called if it has not been overridden by a subclass. You can do that like so:
NSAssert((class_getInstanceMethod([self class], _cmd) == class_getInstanceMethod([MyObject class], _cmd)),
#"Subclass of %# must override -%#",
NSStringFromClass([MyObject class]),
NSStringFromSelector(_cmd));
// ...where overridesSelector:ofBaseClass: looks like:
//
// return ;
Of course, that won't alert you to problems at compile time, but it's better than nothing.
HTH
I think you might be asking how to declare a method that will be implemented some time later somewhere else.
The Objective-C way to do that is to use Protocols.
You declare a protocol like this, usually in a header file
#protocol MyProtocol <NSObject> {
#optional
- (void)optionalMethod;
#required
- (void)requiredMethod;
}
#end
This declares two methods, one which is optional and one is required. To use this protocol you declare the conformance when declaring the class that will implement the protocol
#interface MyConformingClass : NSObject <MyProtocol> {
}
// you don't have to redeclare methods that are declared in the protocol
#end
This new class is checked at compile time for the implementation of requiredMethod so it has to implement it, but it can choose whether or not to implement the optionalMethod
Now, any class that requires instances of objects to conform to the protocol can declare this, for example, in the interface
#interface RequiringClass : NSObject {
MyConformingClass <MyProtocol> *conformingClassObject;
}
…
#end
Again, this is checked at compile time
To make sure that the conforming class implement the #optional methods, we can use this handy structure
if [conformingClassObject respondsToSelector:#selector(optionalMethod)] {
[conformingClassObject optionalMethod];
} else {
// Do something here because the optional method isn't provided
}
Examples of this are all over Cocoa - it's a class can provide a list of actions that it would like to farm out to it's delegate, the delegate adopts the protocol and provides the implementations of those delegate methods. The calling object can then check if this delegate responds to those methods at runtime as I've described above, and call those methods to perform actions, or provide information where ever it needs to.
This is used quite a lot in Objective-C, where classes provide a list of methods that they would like some other class to perform, unlike virtual functions, where a class declares functions it wants subclasses to provide implementations for. Particularly as Composition is favoured over inheritance in the language. Rather than create a subclass to provide an implementation, you just create another class that can do the same thing, and add a reference to that in the class instead.
No.
#dynamic is just an instruction to the compiler that says: "Don't bother generating accessors for this property, I'm going to provide my own."
Using #dynamic with other methods wouldn't be helpful because the compiler doesn't generate any methods other than accessors for you, and of course you're supplying the other methods anyway.
What are you trying to accomplish?