【问题标题】:Multiple Delegates in iOSiOS 中的多个委托
【发布时间】:2012-09-28 07:05:29
【问题描述】:

我正在制作一个对象,用于为我的所有视图控制器下载内容。该对象是单例实例,并且在下载完成后具有接收数据的回调方法。它还有一个委托属性,以便在下载完成后知道要回调哪个对象。

有多个控制器使用这个共享实例,我的问题是如何回调到请求下载的正确视图控制器。

我的方法是使用委托,但问题是由于其他视图控制器也是它的委托,下载对象可能会回调到每个对象,这将很难跟踪。

【问题讨论】:

  • 开始下载的请求能否包含指向数据接收者的指针?然后你可以在每个请求的接收者上调用委托方法。
  • 我遇到了类似的问题并找到了现成的解决方案github.com/aleph7/MultiDelegate

标签: ios delegates callback singleton


【解决方案1】:

如果您只有一个其他对象要向其转发消息,那么一种方法对我有用,那就是创建一个 forwardingDelegate 这不会导致难以调试委托排序的问题,也不会不必要地创建依赖项在另一个物体上。请记住,如果您有很多对象,那么这可能不是最好的方法,它主要用于一个额外的对象,但只要有一个对象接收 SDK 并将其转发到其他对象 [1]。请注意,转发对象所需的每个方法都需要传递它,即使转发对象不使用它也是如此。

例如,如果我需要转发来自 mapView 委托的消息:

 - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated 
{
    // handle this object here. 

    if ([self.forwardingDelegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)])
    {
         [self.forwardingDelegate mapView:mapView regionDidChangeAnimated:animated];
    }

    // or handle this object here. 
}

[self.forwardingDelegate mapView:mapView regionDidChangeAnimated:animated];

转发属性会这样声明。

@property (nonatomic) id<MKMapViewDelegate> forwardingDelegate;

而另一个对象将采用该协议,就好像它正在接收原始消息一样。

[1] 多个委托的数组方法可能会变得棘手,因为您无法像其他帖子中提到的那样控制调用委托的顺序。

【讨论】:

    【解决方案2】:

    虽然我同意这里的大多数答案,但如果您确实想要实现多个委托,您可以声明一个委托数组并向该数组中的所有委托发送消息。如果您的协议具有可选的委托方法,您可以在调用之前使用responds(to aSelector: Selector!) -&gt; Bool 安全地检查(注意内存管理,因为这些委托将在数组中被强引用)。我再次同意多个代表可能是一个糟糕的架构理念,使用块或通知中心会更好地满足您的需求。

    【讨论】:

      【解决方案3】:

      我建议使用其中一种方式

      观察者:

      当您要通知其他对象的使用数据接近原始数据时。例如,当您使用“NSMutableArray”时,您无法通过标准实现模式通知其中一个对象的更改,至少您需要实现一个对你自己来说是不可重复使用的

      通知

      当您与目标对象(需要通知的对象)的交互是单向的时。这意味着您不需要从它们返回任何确认或其他数据。

      委托

      当每个时间步有一个对象需要通知时。

      注意:当您不知道它们何时完成或失败(如网络操作)时,阻止用于成功和失败不是广播即将排队任务的数据的模式

      编辑: how to create notification | multi delegate issues and implementation

      【讨论】:

        【解决方案4】:

        委派似乎不是解决此问题的正确方法。要求请求视图控制器提供一个对象(它自己)和一个选择器供您调用作为完成通知怎么样?当然,您需要一个地方来存储该对象和选择器,直到下载完成。希望您有(或可以创建)一个对象。

        【讨论】:

        • 你也可以使用成功块。
        【解决方案5】:

        实际上听起来委托模式可能不是最好的方法。

        我会改用NSNotificationCenter

        基本的想法是你的单例进行网络连接会发布一个通知(类似postNotificationName:object:userInfo:),说有新数据可用。在此通知中,您可以传递一个字典对象 (userInfo),其中包含您获取的数据,或有关您的模型的哪些部分包含更新数据的信息。

        然后,您的其他视图控制器可以通过调用addObserver:selector:name:object: 注册自己以“观察”这些通知。一般来说,当一个 vc 变得可见时,我会调用 addObserver,而当它被隐藏或转出时,我会调用 removeObserver

        祝你好运!

        【讨论】:

        • 在某些情况下,多个代表很有用。如果您想通过多个视图或数据传输在渲染输出中保持高帧率,则通知比直接委托方法慢。
        【解决方案6】:

        我曾参与过人们尝试使用多个委托的项目,但这基本上是个坏主意。委托模式是关于一个类和它的委托之间的一对一关系。虽然可以通过切换代理的进出来实现某种程度的多重代理,但这更有可能导致不可预知的行为和错误。

        我的建议是改变您对此的看法。在我看来,您有两个选择:

        1. 切换到观察者模式,您可以在其中注册多个观察者,您的主类可以与之交互。这在您的观察者都实现相同的协议以及您的主类想要了解观察者并与他们交互的情况下很有用。

        2. 广播 NSNotifications 以指示状态更改和事件。这是一种更加解耦的方法,因为主类不需要知道谁在听,也不直接与他们交互。其他人可以在闲暇时开始和停止收到通知。它还有一个优点是您不需要创建或实现单独的协议。相反,您可以使用 NSNotificationCenter 注册需要了解更改的类,然后由 NSNotificationCenter 为您处理所有通知的路由。

        【讨论】:

        • 感谢您的解释。 NSNotification 对我来说效果很好。
        • 有点晚了,但是对于那些有类似问题的人:查看发布者/订阅者模式
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-12
        • 1970-01-01
        相关资源
        最近更新 更多