Do code blocks completely replace delegates?
Asked Answered
C

6

25

Now that blocks are finally supported for iphone/ipad development, do these completely remove the need for delegates or are delegates still cleaner as a complete interface implementation while blocks are more appropriate for single tasks?

Chyou answered 3/1, 2011 at 12:27 Comment(0)
V
43

I've been searching for official documentation on this but have yet to find any. Based on reviewing the new classes exposed in iOS 5 and those additions made to pre-existing classes, I'm recommending to my team to presume a delegate protocol but to provide a block instead when there is a direct causal nexus between that specific call and performance of the block.

So, as a rule of thumb, a delegate protocol is correct when there's a need for ongoing communication, the actions causing the communication are diffuse or the actions are emanating from a third source. Blocks are primarily associated with asynchronous actions and single-shot classes in particular.

EDIT: so, some examples:

UIScrollViewDelegate is correctly a delegate protocol because (i) there's a wide range of things that may need to be communicated; (ii) they may need to be communicated in any order and at any time; and (iii) they will be communicated for reasons beyond the delegate's control.

NSURLConnection +sendAsynchronousRequest:queue:completionHandler: correctly takes a block to deliver results because (i) there's exactly one result to report; and (ii) the report comes back as a direct consequence of action taken by the caller.

Vermiculate answered 27/1, 2012 at 15:21 Comment(2)
Please explain a little more if any examples that would be great.ThanksSachi
@Sandy I'm advocating that blocks are a good way to deliver the results of specific actions but a bad foundation for more general conversation. Providing a block is like the listener saying 'this is how you talk to me'; a delegate protocol is like the talker saying 'this is how I will talk to you'. If the talker mainly decides when to talk then it should dictate how it talks. If the listener just asks that a specific thing be done and the results reported back then it makes sense that it says '... and report back like this'.Vermiculate
L
9

Interesting thought - whilst you could use a block/closure in the place of a callback method, I don't see how this could ever be used to replace the delegate system - after all delegation is almost a means of object to object communication and hence the possibilities are a lot richer than simply the execution of an arbitrary piece of code.

As such, I've have to agree with your "more appropriate for single tasks" comment (and even then only certain isolated tasks).

Latia answered 3/1, 2011 at 12:37 Comment(0)
F
8

I was trying to decide if I should leave a comment on other answers or leave an answer of my own. I decided and here it is.

I'm a C# developer primarily so I can easily see how I could replace the entire delegation pattern with blocks because C# has always treated verbs as first class citizens. In fact, that was one of the hardest things to get used to when I started working with Java and the Android platform. That experience made it easier when I learned Objective-C and Cocoa.

I think it's an observer pattern vs. delegation pattern implementation detail that I don't feel particularly strongly about. I'm pretty heavily composition over inheritance oriented so I do use the delegation pattern frequently, even in C#.

I don't think either one should replace the other. I think the two patterns should be used where each is the most appropriate; however, I have found several instances where I would definitely prefer the observer pattern over the delegation pattern in Cocoa.

For example, dealing with the result of UIAlertView I feel should be based on blocks instead of delegates. That always felt a little strange to me, but block weren't available when that particular part of the API was developed. As a result, I was never sure if Apple felt this should be the preferred approach or if that was the only approach at the time.

Recently, I integrated GameKit into one of my games and found that most of the asynchronous calls (in fact, all the ones I've used) don't use delegates; they use blocks. I'd imagine if they could rewrite the UIAlertView today, they'd likely use blocks instead of delegates to handle callbacks following user input. Of course, that's just speculation.

The short answer to your question: I prefer the delegation pattern when composing objects to avoid unnecessarily complex inheritance hierarchies and I prefer the observer pattern when I'm dealing with things that are analogous to events like callbacks and event handlers. I use delegates for the former and blocks for the latter.

Folkmoot answered 14/3, 2012 at 15:42 Comment(1)
Indeed, in iOS 8, UIAlertView was changed by a ViewController. And the UIAlertViewController have actions that use blocks.Ego
S
1

I'm doing my own research on the subject and I found this article to be very instructive, written by Justin Driscoll, and I hope it can help someone else as well.

Here is the link: Communicating with Blocks in Objective-C

Sidsida answered 23/5, 2013 at 13:49 Comment(0)
U
0

Delegates - You can use delegate when you want to know the Process/Events/State. For example In NSURLConnectionDelegate you will get the status of data with two or more delegate methods .didReceive:NSData connectionDidFinishLoading

Blocks - You can use block only when you expect a result or error

Best reference - http://blog.stablekernel.com/blocks-or-delegates/

Unconditioned answered 9/6, 2017 at 3:50 Comment(0)
T
0

The short answer is Yes. But you probably don't want to do it, because it will be very redundant.

Let's see a most common use case of delegate - CollectionViewDelegate, and let's say we want to use its most popular method - collectionView:didSelectItemAtIndexPath.

With delegate, we only need to do one thing :

    @interface MyView () <UICollectionViewDelegate>
    @end

    @implementation MyView {
    ...
    -(void)collectionView:(UICollectionView *)collectionView 
           didSelectItemAtIndexPath:(NSIndexPath *)indexPath {

        // add the implementation here.
    }

How do we achieve this with only block?

    @implementation MyView {
     ...   
     void (^didSelectItemAt)(NSIndexPath*) = ^(NSIndexPath *indexPath) {
          // do a bunch of things to display the cell
          URLFromCell();
          PaneFromURL();
          self.NavigationController.pushView();
      }         
    }

Consider the many delegate methods in CollectionViewDelegate, you need to implement every methods you would like to involve, the code become very hard to read.

At the end, let's look at Apple's definitions of delegate and block:

"A delegate is an object that acts on behalf of, or in coordination with, another object when that object encounters an event in a program. "

While a block is "An Objective-C class defines an object that combines data with related behavior. "

We can safely make the conclusion that block and delegate are designed for different purposes, and good at what they're assigned to. We should use one or the other depends on the goal we want to achieve.

Turpeth answered 15/3, 2019 at 18:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.