Do code blocks completely replace delegates?

2019-01-21 08:09发布

问题:

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?

回答1:

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.



回答2:

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).



回答3:

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.



回答4:

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



回答5:

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/