iOS/Objective-C: How can I mix delegation and blocks? - ios

I have two classes. Delegator uses delegation to send its result. Blocker uses blocks in static methods.
Without changing Delegator, how can I elegantly and easily implement methodWithBlock so that the block is called with the result produced by methodWithDelegate?
Delegator:
#class Delegator;
#protocol Delegate <NSObject>
- (void)delegator:(Delegator *)sender producedResult:(int)result;
#end
#interface Delegator : NSObject
#property (weak, nonatomic) id <Delegate> delegate;
- (void)methodWithDelegate;
#end
#implementation Delegator
- (void)methodWithDelegate
{
// Some asynchronous computation resulting in
[self.delegate delegator:self producedResult:42];
}
#end
Blocker:
#interface Blocker : NSObject
+ (void)methodWithBlock:(void(^)(int result))block;
#end
#implementation Blocker
+ (void)methodWithBlock:(void(^)(int result))block
{
// How to call Delegator's methodWithDelegate and return
// the result using block ?
...
}
#end
Explored solutions:
Wrap Delegator into a new class or a category and create a method returning a block, as suggested in this answer. These solutions work but are far too complicated and time-consuming.
Make Blocker conform to the protocol Delegate and keep the block in a property, instantiate it within the method methodWithBlock, and call the block when the delegation method is called. This does not work, as there is no strong pointer to this new instance and it gets destroyed.
In the previous solution, to avoid losing the instance by lack of a strong pointer, keep a static array of the current instances of Blocker and delete them in the delegate callback method. Again, this solution works but is too complicated.

Rather than delegates and block properties, use an observable property to communicate results. It's cleaner (and easier) as the working object does not have to worry its pretty little head about who may be watching it. And the watching objects don't have to worry about conforming to any special protocol.

The elegant and easy solution is to just add a block-based method to your Delegator (e.g. through a category). I know you said you can't do that, but we have to admit, then, that any other block based solution where you're creating new classes to yield the effect you want fails the elegance test.
Having said that, if you desperately need block-based methods and cannot extend Delegator, then I'd lean towards option 2, except rather than making those class methods, make them instance methods, and have Blocker instantiate Delegator and define wrapper methods so that classes that would have used Delegator can now use Blocker, but with completion blocks rather than delegate callbacks. And the class that was previously instantiating Delegator can now instantiate Blocker instead.

Related

Objective C: Declaring a selector but implementing it in objects category

I have a framework in obj-c which is included by other modules. I want to allow the modules which are going to include it to provide their own implementation for certain methods.
I can't use subclassing because of some issues around serializing these objects. So, have to rely on using category.
I am thinking of declaring a method/selector for the object and then modules will define the category and implement that method. Something like below:
Framework will declare interface like below:
#interface framework:NSObject
- (void)methodToBeImplemented;
#end
#implementation framework()
- (void)invokeClientDefinedMethod
{
if([self respondsToSelector:#(methodToBeImplemented)]) {
[self methodToBeImplemented];
}
}
//Module-1 will link against this framework and define the category
#implementation framework(methodImplementor)
- (void)methodToBeImplemented
{
...
}
#end
Can I choose not to implement methodToBeImplemented at all in framework and implementation to be provided by the modules themselves.
I know that I can do it performSelector route. But I cringe to do so because I want to send pointers to my method which is not really possible with performSelector
If possible, I would highly recommend using a delegate pattern for your object so that callers can pass a delegate that conforms to a protocol rather than directly extending the class. That's the normal way to implement this kind of system. But if there's a particular reason a delegate is not possible, you can build what you're describing.
What you're looking for is an informal protocol, which is how almost all protocols were handled prior to the introduction of #optional.
What you want to do is define a category on your class in your public header:
#interface Framework (OverridePoints)
- (void)methodToBeImplemented
#end
This declares that such a method may exist, but it does not enforce its actually being implemented. The key is having a name in the parentheses. This can be anything (I used "OverridePoints" here), but it cannot be empty since that would be an extension instead of a category.
Once you have that, then the rest of your ideas work. You can test for respondsToSelector:, and the consumer can implement (or not implement) the category methods just as you describe.
The one danger is that there is nothing preventing multiple parts of the program implementing the same method in categories. That is undefined behavior, but the compiler will not catch it for you.

How to implement two delegates of the same type in one class?

I am looking for good pattern for such a situation. Let's we have class with delegate:
#protocol MyDelegate
-(void) someEvent;
#end
#interface MyServiceClass
#property (nonatomic,weak) id<MyDelegate> delegate;
#end
And we have two instances of this class. For example serviceObject1 and serviceObject2. Now in our controller we want to receive events from both of instances:
-(void) registerDelegates {
serviceObject1.delegate=self;
serviceObject2.delegate=self;
}
-(void) someEvent {
// do something
}
All is good except that events from both instances will be thrown to one someEvent method. For me will be more comfortable to separate events from serviceClass1 and serviceClass2 to different methods.
I saw three approaches but does not like any of them:
Send instance of caller as argument of someEvent and check from which instance this event is and redirect to appropriate method.
Create two fake objects in my controller and register them as delegates to service1Class. And from this objects call different methods in my controller.
Use anonymous blocks instead of delegates. Good decision but i don't know how to unregister them.
May be exists another solution that i missed?
The way this is handled is by passing the MyServiceClass instance as one of the method parameters, basically what you wrote for #1.
That's how Apple does it and it's kind of standard practice.
#protocol MyDelegate
-(void) someEventFromService:(MyServiceClass *serviceClass);
#end

How does delegate call differ from normal method call ?

Whenever I wanted to inform something to parent class, I have used delegate instead of calling directly parent's functions. I have implemented like this...
eg:
CustomClass *custom = [[CustomClass alloc] init];
// assign delegate
custom.delegate = self; // Here we are giving parent instance like normal method call.
[custom helloDelegate];
In custom class, I have intimated parent like below....
-(void)helloDelegate
{
// send message the message to the delegate
[_delegate sayHello:self];
}
So my doubts , how does it differ from direct call?. Setting delegate variable with self is somewhat equal to giving the parent instance to child and let the child call the function whenever required, how does protocols help here or why do we need protocols? what is the advantage?
thanx
A working example of the advantage of using a delegate as opposed to using a direct relation.
Say you are writing a universal app. You have two view controllers in your code iPadViewController and iPhoneViewController and they both need to get data from a web service. So you create a class for you web service call webServiceDownloaderClass.
Now, both your view controllers need to be notified when the webServiceDownloaderClass has finished.
Your options here...
Option 1 strong coupling
In you iPadViewController you define a method - (void)webServiceDidGetArray:(NSArray *)array;. And in the iPhoneViewController you define the same method.
In order for the webServiceDownloaderClass to call these methods it now needs a reference to each of the controllers...
#property (nonatomic, strong) IPadViewController *iPadController;
#property (nonatomic, strong) IPhoneViewController *iPhoneController;
and then when it finishes it needs to determine which one to call...
if (iPadController) {
[iPadController webServiceDidGetArray];
}
etc....
The cons here are that the view controllers are sort of defining what the web service class does when it is finished. Also, if you add another controller you have another property and no actual guarantee that the controller you referenced actually has the method you are trying to call.
Option 2 delegation
In your we service class you define a protocol.
#protocol WebServiceDownloaderDelegate <NSObject>
- (void)webServiceDidGetArray:(NSArray *)array
#end
and a delegate...
#property (nonatomic, weak) id <WebServiceDownloaderDelegate> delegate;
Now you are defining the actions of the web service class in the web service class. And you only need one reference to any class wants to be the delegate. Also, any class can be the delegate. So now both the iPad and iPhone controller can be the delegate and by conforming the the protocol they are "promising" the web service class that they will implement the required method - (void)webServiceDidGetArray:(NSArray *)array;.
Of course, this is just one case where delegates can be useful.
There are also cases for when you should possibly use a direct relationship rather than delegation.
your question is really about the difference between subclassing rather than implementing protocols (or interfaces in other languages like java)..
with delegates, you are implementing a protocol.. (which is a contract between the class referencing the delegate and the delegate itself).. this gives you more flexibility than subclassing because with subclassing you are automatically inheriting all the methods in the superclass (which is far more restricting than simply using some of the methods of another class.. in other words: subclassing = is a relationship.. whereas as implementing a protocol (same as delegation) = has a relationship.
if you read any book about design patterns.. they will talk extensively about the advantages of loose coupling your code and writing code that prevents modification but allows extension etc etc.. basically using delegation rather than subclassing is one way of fulfilling those design best practices.
A delegate call is not different from an ordinary method call!
What is different is how things are used, and this has nothing to do with the call mechanism. Delegates are used to decouple the definition of the code providing the delegate service from the code "consuming" the delegate service, so that the "consumer" (which, oddly, is usually a service on behalf of the delegate provider) does not have to be coded to know about THAT SPECIFIC delegate provider.
In Objective C delegates are commonly implemented using "protocols", but this is far from the only use of protocols. Objective C uses them extensively in providing common interfaces among the various Cocoa classes.
And, in limited circumstances, one can legitimately implement a delegate using a common superclass rather than a protocol.
If you have two classes that are part of the same development effort and which would not be likely to ever be used apart from each other, there is no need to employ the delegate "pattern" to facilitate communication between them, even though they are is a service-consumer/service-provider relationship. The only reason to do so would be "on spec", in case the "service" were ever reused unchanged in a different project.

What exactly are protocols and delegates and how are they used in IOS?

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>

Are these points about delegates in IOS correct? Yes or no?

I've been struggling with delegates for a long time. It's a very hard concept for me for some reason. I feel like now I have more knowledge, but I'm still far from being confident.
Please tell me if any of these are incorrect/incomplete and why. Thank you.
Delegates implement protocols (unimplemented method headers)
An object (a delegator) can register a delegate (that implements a protocol). This can be done by declaring a property of type id that implements a protocol:
#property (weak, nonatomic) id <MyProtocol> myDelegate;
The delegator can call certain methods (as specified in MyProtocol protocol) on the delegate
Any class that implements the protocol and has to be Delegator's delegate, can declare itself as such:
MyDelegator* myDelegator = segue.destinationViewController;
myDelegator .delegate = self;
Advantages of using a delegate:
a. Reduces coupling (Delegate and Delegator are no longer dependent on each other) which is an important OO design principle
b. makes Delegator more generic; it can now work with other objects, not just this Delegate
1,2 - yes
3 - can call any method of MyProtocol,
4 - correct.
5 - almost right, a very good explanation can be found here delegate and controllers
Yes. But the protocols can be informal.
Yes.
Yes.
Yes and no. Again, the delegate could implement the methods informally... but then you'd want the delegator to verify if the delegate respondsTo (or implements) a method before calling it.
The delegate doesn't necessarily need to set itself as the delegator's delegate (in fact, it shouldn't). Analogy: A business specialist comes to my company and tells my boss to delegate the administrative paperwork to his secretary. The secretary (the delegate) didn't tell the boss (the delegator) to give it work... a third-party did.
A delegate doesn't have to register itself as the delegate (again, it shouldn't). It needs only be able to do the work. Normally the delegate would know nothing (no pointers to) the delegator. So the delegate wouldn't have MyDelegator* myDelegator = segue.destinationViewController;, no.
A) Yes!
B) Yes. Essentially what "reduce coupling" is;
Adding a C): It also allows you to change the behaviour on-the-fly by simply changing the delegate at runtime.

Resources