Delegates in IOS - Some clarification required - ios

I'm only really beginning IOS development but have a few years dev of ASP.net through C#. To be honest I've never had a real need to understand delegates / events etc. before, I know that I'm using them when programming web.forms but a lot of the functionality is taken care of by the framework, behind the scenes.
So now that I'm developing in IOS I'm forced to try to understand how they function (I'm presuming here that the theory of delegates / events is the same across languages, maybe I'm wrong). Anyway, the following line of code in IOS:
if ([self.delegate respondsToSelector:#selector(startImporting:)])
{
[self.delegate startImporting:self];
}
Am I right in thinking that, in pseudo code, it means something along the lines of:
If the method/class calling this method has a method in it called 'startImporting' then call the method 'startImporting' within the calling class.
Hope that's clear. If that's the case then would it essentially be the same as having a static method in C# that you could call with something like:
myImportClass.startImporting();
Presumably not, or that's how it would be done. So, am I missing the whole point of delegates, their benefits etc? I've read what they are over and over and while it makes sense, it never clicks, I never (in web forms anyway) have really seen the benefit of using them.
This becomes increasingly important as I'm moving to using lambda expressions in .net and they're closely linked to delegates in C# so while I can just start using them, I'd prefer to know why and what benefit delegates actually are.

The delegation pattern in Cocoa is used to inform (report progress, etc.) or query (ask for credentials, etc.) another object without knowing much about it.
Typically, you use a protocol to define what methods you will call on the delegate and the delegate then needs to conform to that protocol. You can also add methods that the delegate doesn't need to implement (optional). When you do so, you'll have to call -respondsToSelector:, because you don't know whether the delegate wants the particular method to be called or not.
An example:
You have a class that produces something, let's call it Machine and a worker of the class Worker. The machine needs to be adjusted for the task:
Machine *machine = [[Machine alloc] init];
[machine prepareWithParameters:myParameters];
Now that we have the machine we want to produce a massive amount of Stuff:
[machine produceStuff];
Okay, we're done. But how do we know when an unit of Stuff has been produced? We could have our worker constantly standing beside our machine and wait:
while (![machine isFinished]) {
if ([machine didProduceStuff]) {
Stuff *stuff = [machine producedStuff];
[self doSomethingWithStuff:stuff];
}
else {
// Get a very large coffee...
}
}
Wouldn't it be great if the machine did inform us automatically, when it's done with producing an unit of Stuff?
#protocol MachineDelegate <NSObject>
#optional
- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff;
#end
Let's add the worker as a delegate of machine:
Worker *worker;
Machine *machine = [[Machine alloc] init];
[machine prepareWithParameters:myParameters];
[machine setDelegate:worker]; // worker does conform to <MachineDelegate>
[machine produceStuff];
When Machine is done producing something, it will then call:
if ([[self delegate] respondsToSelector:#selector(machine:didProduceStuff:)])
[[self delegate] machine:self didProduceStuff:stuff];
The worker will then receive this method and can do something:
- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff {
[self doSomethingWithStuff:stuff];
if ([machine isFinished])
[self shutDownMachine:machine];
}
Isn't that much more efficient and easier for the worker? Now he can do something more productive than standing besides the machine while the machine is still producing. You could now add even more methods to MachineDelegate:
#protocol MachineDelegate <NSObject>
#required
- (void) machineNeedsMaintenance:(Machine *)machine;
- (void) machine:(Machine *)machine fatalErrorOccured:(Error *)error;
- (BOOL) machine:(Machine *)machine shouldContinueAfterProductionError:(Error *)error;
#optional
- (void) machineDidEnterEcoMode:(Machine *)machine;
- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff;
#end
Delegates can also be used to change the behavior of an object without subclassing it:
#protocol MachineDelegate <NSObject>
#required
- (Color *) colorForStuffBeingProducedInMachine:(Machine *)machine;
- (BOOL) machineShouldGiftWrapStuffWhenDone:(Machine *)machine;
#end
I hope I could help you understand the benefit of abstracting your code using delegates a little bit.

Understanding the MVC model and the use of Protocols and notifications is critical to grasping the use and purpose of delegates. Think of them as types of responders for different events related to a specific action.
Hera are some useful links in stackOverflow:
Delegate and notifications
Protocols and delegates
Hope it helps

delegates are useful in getting callbacks from other class
so why to use delegate:
that is we call a method on a class... that's normal... if we want the instantiated class to let us call back... that's where delegates comes in handy...
simple example:
You download songs from a site using a method on one class
once the class completes downloading you want the class to let you know.
//protocol declaration
#protocol DownloadProtocol <NSObject>
-(void)OnFinish;
#end
//SOng download class
#interface songs
#property(Strong,nonatomic) id<DownloadProtcol> delegate;
-(void)Download;
#end
#implementation songs
-(void)Download
{
///the code to download goes here
[self callTheCallingClass];
}
-(void)CallTheCallingClass
{
[self.delegate OnFinish];
}
#end
//
#interface mainclass<DownloadProtocol>
#end
#implementation mainclass
-(void)viewDidload
{
Songs *s=[[SOngs alloc]init];
s.delegate=self;
[s download];
}
-(void)OnFinish
{
NSlog(#"Called");
}
#end
see the delegation is achieved through protocol in objective c. I think you can understand the syntax of it.
In the songs class we create a property for that protocol. we keep it the type as ID... because the type is not known at compile time.
in the songs class once we complete the download we call the protocol method...
In the main class first we adopt the protocol syntax
class
the above is syntax of that
the we instantiate the songs class
then assign the main class object(self) to delegate of songs class
then we have to apply the protocol class in .m by adding method name from protocol
so from now on whenever songs class call the protocol method through delegate instance variable....out protocol method adoption on main class gets run
try this code hope it helps...
if you want more info on this topic google it as delegate design pattern
the main benefit is
it promotes loosely coupled programming...

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

Is it possible to pass completion blocks to a delegate parameter in Objective-C?

Or does the method have to be written to accept a block? Put another way, if we don't control the code that defines the method, are we at the mercy of using delegates if that's how it's defined, or is there a way to pass two anonymous functions (blocks) within a method call that is expecting a delegate?
Technically the answer is no, if some library or class works with delegates there is probably a good reason and the smart and easier thing to do is use them.
If for some reason you're really interested in using blocks because it's more natural for your problem domain you can implement a wrapper.
Super weird example ahead.
For instance, in UITableViewDataSource delegate you have a method to obtain the number of rows in each section:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
In order to use it you have to set the table dataSource property to some object that implements that method. The usual stuff.
You can create a data source wrapper tha implement the original protocol and a new one you define to use your desired blocks interface.
typedef NSUInteger (^RowsCounterBlock)(NSInteger section);
#protocol RowsCounter
- (void)tableViewController:(id)controller countRowsWithBlock:(RowsCounterBlock)block;
#end
// we implement both the original protocol and our block based protocol
#interface ComplexDataSource : NSObject <UITableViewDataSource, RowsCounter>
{
#property(strong) RowsCounterBlock counterBlock;
}
// save a block that knows how to count rows
- (void)tableViewController:(id)controller countRowsWithBlock:(RowsCounterBlock)block
{
controller.dataSource = self;
self.counterBlock = block;
}
// use the saved block to implement the method defined in the original delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (!self.counterBlock) return 0;
return self.counterBlock(section);
}
#end
Then in your table controller:
self.source = [ComplexDataSource new]; // save the data source in a property
[self.source tableViewController:self
countRowsWithBlock:^NSUInteger(NSInteger section) {
// this will be called each time the table view needs to ask
// for the number of rows via the proxy delegate
<#do your magic#>
return <#rows#>;
}]
And the answer is still no, because you're using the original delegate...but under the hood your primary interface now is block based.
Short question is no, if the method is defined to get a delegate parameter, you're out of luck if you want to use a block.
But, as the other people said, sometimes a delegate pattern is better than a block, it all comes down to the use cases. Maybe if the API designer chose a delegate instead of a block, there is a reason.
IMHO blocks are most useful when it comes to success or failure callbacks, but in a lot of other cases a delegate is still better (though, I would also love to use an anonymous class, Java-style :) but that's just because sometimes we're lazy)
First of all, delegation is in many cases better than using a closure. In other cases closures are better. So at the very beginning one should ask: Why?
However: What is the problem to define a delegate method that calls a closure?

Preferable design pattern for model with background networking

I'm developing a model class that provides data parsed from the web. Of course, I'd like my application to be responsive and thus networking should be done on separate thread/queue.
That leads to the question: how should I design the #interface of my class?
The main requirements are:
It should deliver data from Model to Viewcontroller :) ;
It shouldn't block the main (UI) thread;
It should be easy to understand and follow by other developers.
From what I've learned from WWDC2012 video, "Building Concurrent User Interfaces on iOS" Apple recommends to move the concurrent code to the class itself that uses model.
Let's say we have Posts class (Posts.h/.m) that should provide ViewController with latest posts in NSArray* format.
Option I -- concurrency is in class users
The class itself is not concurrent, but the users are:
//Posts.h:
#interface Posts : NSObject
- (NSArray*)getPostsForUser:(NSString*)user;
#end
//ViewController.m
#implementation ViewController
- (void)someFunctionThatUpdatesUI
{
//<...>
NSOperationQueue *q = [[NSOperationQueue alloc] init];
[q addOperationWithBlock:^{
NSArray *currentPosts = [Posts shared] getPostsForUser:#"mike";
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
//UI should be updated only on main thread
[self updateUIWithPosts:currentPosts];
}];
}];
//<...>
}
The main disadvantage of this approach is the necessity to repeat almost the same code in every ViewController. What if there are dozens of them?
Option II -- concurrency with completion handlers pattern
Second option that I currently use in my app is a completion handler pattern. As the completion handler is called only after some long networking is performed, it doesn't block the main thread:
//Posts.h:
#interface Posts : NSObject
- (NSError*)getPostsForUser:(NSString*)user
withCompletionHandler:(void(^)(NSArray*))handler;
#end
#implementation Posts
- (NSError*)getPostsForUser:(NSString*)user
withCompletionHandler:(void(^)(NSArray*))handler
{
//<...>
dispatch_async(dipatch_get_global_queue(0, 0), ^{
//Do some may-be-long networking stuff here,
//parse, etc and put it into NSArray *result
dispatch_async(dipatch_get_main_queue(), ^{
handler(result);
});
});
//<...>
}
//ViewController.m
- (void)someFunctionThatUpdatesUI
{
//<...>
[Posts shared] getPostsForUser:#"mike"
withCompletionHandler:^(NSArray* posts){
//updateUI with posts
}];
}
From my point of view, this way is good but the #interface is rather complicated, the method names are long and (from my point of view) obfuscated.
Option III -- delegate pattern
Another option that I see is the delegate pattern. What bothers me is that only one ViewController may be the delegate, thus it leads to necessity to set every VC as delegate in - viewWillAppear, which is easy to forget.
//Posts.h:
#protocol PostUpdate<NSObject>
- (void)updateUIWithPosts:(NSArray*)posts FromUser:(NSString*)user;
#end
#interface Posts
- (NSError*)updatePostsFromUser:(NSString*)user;
#property(nonatomic, weak) id<PostUpdate> delegate;
#end
//ViewController.m:
#implementation ViewController<PostUpdate>
- (void)viewWillAppear
{
//<...>
[Posts shared].delegate = self;
}
- (IBAction)getLatestsPostButtonPressed:(id)sender
{
[[Posts shared] updatePostsFromUser:#"mike"];
}
// protocol PostUpdate
- (void)updateUIWithPosts:(NSArray*)posts FromUser:(NSString*)user
{
//updating UI with posts
}
#end
So here are the questions:
What else patterns fit the requirements to deliver data from Model to Controllers in non-blocking way?
What option would you recommend based on your experience, practise or theoretical knowledge?
Short answer
I recommend going with option-II as it's the most suitable solution in your case.
Long answer
First of all, none of the three solutions is wrong, but we are only trying to figure out the best one among them for your case.
• The problem with option-I is that it's always synchronous and will block the calling thread while you need it to be asynchronous, and therefore, you'll find yourself always calling it from a background thread which means there will be a lot of repeated code that will make maintenance harder (This option can be a good solution if you need the method to be asynchronous sometimes and synchronous most of the time).
• The option-II solves the problem by providing a way to notify the caller thread when the data is ready, and the added parameter isn't really a disadvantage compared to the easiness of use and flexibility it gives. And if you think you will not really need the added parameter in some cases, you can simply make another synchronous version of the method without that parameter:
- (NSArray *)fetchPostsForUser:(NSString*)user; /// Synchronous
- (void)fetchPostsForUser:(NSString*)user /// Asynchronous
completion:(CompletionHandler)completion;
CompletionHandler is defined as following:
typedef void (^CompletionHandler)(NSArray *result, NSError *error);
• The third option isn't really a good solution for your problem. Delegates should be used to deliver events about the class itself, not to deliver responses to previously called methods. Also, notice than you can only have one delegate and this means you can't call such method from two different controllers at the same time.
Option 1 is bad for the reason you mention.
Option 3 is bad because you may have network data returned in a different order than requested if you have 2 network requests going at the same time. This may make it more difficult than necessary to update your UI properly, depending on your data. (For example, items could appear out of order.)
Option 2 seems ideal. It has the benefits of Option 3, plus you get the scope-capturing benefit of Objective-C blocks. You may want to look at the networking library AFNetworking, which approximately follows this pattern. One additional consideration is that you should keep your data networking & serialization in a separate class from data persistence / processing. For example, one class should download data, turn it into an array of Post objects, and send it to the callback block. That callback block could be a view controller, or it could be a separate class that caches the data to disk (using NSCoder or Core Data, for example.) This approach will keep your code as flexible as possible.

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

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.

Resources