代码块是否完全取代了代理?

时间:2011-01-03 12:27:28

标签: ios4 delegates

现在最终支持iphone / ipad开发的块,这些是否完全消除了委托的需要,或者代理仍然更清洁作为完整的接口实现,而块更适合单个任务?

6 个答案:

答案 0 :(得分:42)

我一直在寻找关于此的官方文档,但还没有找到。在回顾iOS 5中公开的新类以及对已有类的新增类的基础上,我建议我的团队设定一个委托协议,但是当存在直接因果关系时提供一个块在特定呼叫和块的性能之间。

因此,根据经验,当需要持续通信时,委托协议是正确的,导致通信的动作是分散的,或者动作是从第三个源发出的。块主要与异步操作和单击类相关联。

编辑:所以,一些例子:

UIScrollViewDelegate是正确的委托协议,因为(i)可能需要传达的内容很多; (ii)他们可能需要在任何时间以任何顺序进行沟通; (iii)他们将以超出代表控制权的原因进行沟通。

NSURLConnection +sendAsynchronousRequest:queue:completionHandler:正确地使用一个块来传递结果,因为(i)只有一个结果要报告; (ii)报告的回复是调用者采取行动的直接后果。

答案 1 :(得分:9)

有趣的想法 - 虽然您可以在回调方法的位置使用块/闭包,但我看不出如何使用它来替换委托系统 - 在所有委托几乎都是对象的对象之后沟通,因此可能性比简单地执行任意代码要丰富得多。

因此,我必须同意你的“更适合单一任务”的评论(甚至只有某些孤立的任务)。

答案 2 :(得分:8)

我试图决定是否应该对其他答案发表评论或留下我自己的答案。我决定在这里。

我主要是C#开发人员,因此我可以轻松地看到如何用块替换整个委托模式,因为C#始终将动词视为一等公民。事实上,这是我开始使用Java和Android平台时最难习惯的事情之一。当我学习Objective-C和Cocoa时,这种经历变得更加容易。

我认为这是一个观察者模式与委托模式实现细节,我并不特别强烈。我非常重视继承导向,所以我经常使用委托模式,即使在C#中也是如此。

我不认为任何一方应该取代另一方。我认为应该使用两种模式,每种模式都是最合适的;但是,我发现了几个实例,我肯定更喜欢观察者模式而不是Cocoa中的委托模式。

例如,处理UIAlertView的结果我觉得应该基于块而不是委托。这对我来说总觉得有些奇怪,但是当API的特定部分被开发出来时,阻止是不可用的。结果,我从未确定Apple是否认为这应该是首选方法,或者当时这是当时唯一的方法。

最近,我将GameKit集成到我的一个游戏中,发现大多数异步调用(事实上,我使用的所有异步调用)都没有使用委托;他们使用积木。我想如果他们今天可以重写UIAlertView,他们可能会使用块代替委托来处理用户输入后的回调。当然,这只是猜测。

对你的问题的简短回答:我在编写对象时更喜欢委托模式,以避免不必要的复杂继承层次结构,当我处理类似于回调和事件处理程序之类的事情时,我更喜欢观察者模式。我使用前者的代表和后者的块。

答案 3 :(得分:1)

我正在研究这个问题,我发现这篇文章非常有启发性,由Justin Driscoll撰写,我希望它也可以帮助其他人。

以下是链接:Communicating with Blocks in Objective-C

答案 4 :(得分:0)

委托 - 您可以在想要了解流程/事件/状态时使用委托。例如,在NSURLConnectionDelegate中,您将获得具有两个或更多委托方法的数据状态.didReceive:NSData connectionDidFinishLoading

块 - 只有在预期结果或错误时才能使用块

最佳参考 - http://blog.stablekernel.com/blocks-or-delegates/

答案 5 :(得分:0)

简短的回答是。但是您可能不想这样做,因为这将非常多余。

让我们看一下委托的最常见用例-CollectionViewDelegate,假设我们要使用其最受欢迎的方法-collectionView:didSelectItemAtIndexPath。

有了委托,我们只需要做一件事:

    @interface MyView () <UICollectionViewDelegate>
    @end

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

        // add the implementation here.
    }

我们如何仅用块来实现?

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

考虑CollectionViewDelegate中的许多委托方法,您需要实现要包含的每个方法,代码变得很难阅读。

最后,让我们看一下Apple对委托和阻止的定义:

“委托是一个在另一个对象遇到程序中的事件时代表另一个对象或与另一个对象协作的对象。”

虽然块是 “ Objective-C类定义了一个将数据与相关行为结合在一起的对象。”

我们可以安全地得出以下结论:block和委托是为不同目的而设计的,并且擅长将它们分配给他们。我们应该使用一个或另一个取决于我们要实现的目标。