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

问题描述 投票:25回答:6

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

ios4 delegates
6个回答
42
投票

我一直在寻找关于此的官方文档,但还没有找到任何。在回顾iOS 5中公开的新类以及对预先存在的类添加的新类的基础上,我建议我的团队假定一个委托协议,但是当该特定调用与之间存在直接的因果关系时,提供一个块。块的性能。

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

编辑:所以,一些例子:

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

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


9
投票

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

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


8
投票

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

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

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

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

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

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

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


1
投票

我正在对这个主题进行自己的研究,我发现这篇文章非常有启发性,由Justin Driscoll编写,我希望它也可以帮助其他人。

这是链接:Communicating with Blocks in Objective-C


0
投票

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

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

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


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类定义了一个将数据与相关行为相结合的对象”。

我们可以安全地得出结论,块和委托是为不同目的而设计的,并且擅长于它们被赋予的内容。我们应该使用一个或另一个取决于我们想要实现的目标。

© www.soinside.com 2019 - 2024. All rights reserved.