iOS中的多个委托

iOS中的多个委托,ios,delegates,callback,singleton,Ios,Delegates,Callback,Singleton,我正在制作一个对象,用于下载我所有视图控制器的内容。该对象是singleton实例,下载完成后有一个回调方法,其中包含接收到的数据。它还有一个委托属性,以便在下载完成后知道调用哪个对象 有多个控制器使用此共享实例,我的问题是如何回调请求下载的正确视图控制器 我的方法是使用委托,但问题是,由于其他视图控制器也是它的委托,下载对象可能会回调到每个对象,这将很难跟踪。我曾参与过一些项目,人们试图使用多个委托,这基本上是个坏主意。委托模式是类与其委托之间的1:1关系。虽然可以通过切换代理来实现某种程度的

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

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


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

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

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

  • 切换到观察者模式,在该模式中可以注册多个观察者,主类可以与之交互。当您的观察者都实现相同的协议时,以及当您的主类希望了解观察者及其交互时,这非常有用

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


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

    我会转而调查通知中心

    基本思想是,进行网络连接的单身汉会发布一个通知(类似于
    postNotificationName:object:userInfo:
    ),表示新数据可用。在此通知中,您可以传递一个dictionary对象(
    userInfo
    ),该对象保存您获取的数据,或者传递有关模型哪些部分包含更新数据的信息

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


    祝你好运

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

    我建议您使用以下方法之一

    观察者:

    当使用数据时,您希望通知其他对象的数据接近于原始对象。例如,当您使用“NSMutableArray”时,您不能通过标准实现模式通知其中一个对象中的更改,至少您需要为自己实现一个不太可重用的数据

    通知

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

    代表

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

    注意:块使用成功和失败不是一种模式,当您不知道任务何时完成或失败时(如网络操作),它不会将数据广播到队列任务

    编辑:
    |

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

    一种方法,如果您只有一个要转发消息的其他对象,那么这对我来说是可行的,即创建一个
    转发委托
    ,这不会导致难以调试委托顺序的问题,也不会不必要地创建对其他对象的依赖性。请记住,如果您有许多对象,那么这可能不是最好的方法,它主要用于一个额外的对象,但只要有一个对象接收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;
    
    @属性(非原子)id forwardingDelegate;
    
    另一个对象将采用该协议,就好像它正在接收原始消息一样


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

    开始下载的请求是否会包含指向数据接收者的指针?然后你可以打电话给德莱格