Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 我应该如何处理在Objective-C中对同一个委托进行多次回调的需要?_Iphone_Objective C_Delegates_Cocoa Design Patterns - Fatal编程技术网

Iphone 我应该如何处理在Objective-C中对同一个委托进行多次回调的需要?

Iphone 我应该如何处理在Objective-C中对同一个委托进行多次回调的需要?,iphone,objective-c,delegates,cocoa-design-patterns,Iphone,Objective C,Delegates,Cocoa Design Patterns,我创建了一个库,可以下载JSON数据,然后将其放入NSDictionary中。我用一个简单的Twitter引擎来包装这个类,它允许我拉我的朋友的时间线,发布一个更新,并发布一个关于我的GPS位置的更新。从我对Objective-C的有限经验来看,将一切联系起来的方法是授权。我设置了一个委托属性,它将异步结果回调给选择器或方法签名。我甚至可以在委托上创建一个可选或必需的接口,这将允许Xcode帮助我实现委托。为了了解如何在Objective-C中使用委托,我创建了这个简单的项目 它定义了一个工人

我创建了一个库,可以下载JSON数据,然后将其放入NSDictionary中。我用一个简单的Twitter引擎来包装这个类,它允许我拉我的朋友的时间线,发布一个更新,并发布一个关于我的GPS位置的更新。从我对Objective-C的有限经验来看,将一切联系起来的方法是授权。我设置了一个委托属性,它将异步结果回调给选择器或方法签名。我甚至可以在委托上创建一个可选或必需的接口,这将允许Xcode帮助我实现委托。为了了解如何在Objective-C中使用委托,我创建了这个简单的项目

它定义了一个工人类,允许您使用委托初始化该类。当使用doWork方法完成工作时,它会在委托上查找方法签名以向其发送消息。它使用以下代码

if([[self delegate] respondsToSelector:@selector(workFinished:)]) {
    NSString *msg = @"That's it? Easy!";
    [[self delegate] workFinished:msg];
}
它查找workFinished:方法以传回消息。我将此方法签名声明为可选接口,在标题Worker.h中使用以下代码

  @protocol WorkerNotifications
   @optional
   - (void) workFinished: (NSString *) msg;
   @end
您可以从下载中查看项目的其余部分,了解所有详细信息。但这两个代码片段展示了这种委托模式的工作原理。但是对于Twitter类,我需要知道启动异步操作的方法的上下文,该异步操作导致对委托方法的回调。如果我从调用类多次调用sendUpdate方法,我应该如何知道回调的上下文

通常使用JavaScript、Java或C等语言时,我会创建一个内联闭包或匿名类,该类可以访问起始上下文,但目前iPhone上的Objective-C不可能做到这一点。我发现这个问题已经在StackOverflow上被问到和回答了

因此,我所做的是跳过可选接口,而是传入一个选择器,当异步操作完成时,Twitter类将调用该选择器。启动此操作的调用看起来像

CMTwitterEngine *engine = [[CMTwitterEngine alloc] initWithDelegate:self];
[engine setSendUpdateFinished:@selector(sendUpdateFinished:)];
[engine setSendUpdateFailed:@selector(sendUpdateFailed:)];
[engine setParsingSendUpdateFailed:@selector(parsingSendUpdateFailed:)];
[engine setUsername:TWITTER_USERNAME pass:TWITTER_PASSWORD];
[engine sendUpdate:statusUpdateText.text];
此代码首先以self作为委托初始化引擎引用。为了附加回调,我在sendUpdate方法签名上最初使用的选择器中发送回调,但是方法调用变得相当长。我选择简单地设置选择器的属性。这一切工作,但我不确定我喜欢这是如何工作,因为它只是部分解决了我的问题

为了完成这个示例,我完成了异步工作,并最终在内部调用了一个方法,该方法查找给定的选择器,并在它被定义时调用它

- (void)sendUpdateFinished:(NSDictionary *)dictionary {
    if (self.sendUpdateFinished != nil) {
        [self.delegate performSelector:self.sendUpdateFinished withObject:dictionary];
    }
}
我可以传递状态消息作为Twitter更新发送,但我仍然没有发起呼叫的上下文。如果我想多次调用sendUpdate,而第一个异步调用仍在运行,该怎么办?如果第二个电话先结束怎么办?它们都将self作为代理,因此我要么以某种方式跟踪上下文,要么将它们传递给不同的选择器以区分它们,这也不能满足我的需要。如果我有3个、4个或5个异步调用,会发生什么?我需要知道哪些邮件发送成功,以及何时完成

看来,我能做到这一切的唯一方法是创建一个类,该类保存上下文所需的所有属性,让该类充当异步Twitter方法调用的委托,然后向父类(可能是UIViewController)报告。我会采用这种方法,但我还没有读过这种方法,也没有看到任何这样做的示例代码


你会怎么做?你将如何处理多个异步调用,这些调用可能以不同的顺序结束,而不是外出,然后在完成后用上下文处理它们。

一个要考虑的事情是使用通知来代替。简化了代码,减少了耦合。

我认为您的情况是使用NSNotificationCenter的好地方

我不得不附议(或附议)之前在NSNotificationCenter发布的答案,这可能就是您在这里寻找的答案

本质上,当可能有许多委托都需要对已发生的单个操作或事件做出响应时,通常会使用通知。可以将其视为一对多类型的委托或观察者模式的实现。需要了解的基本情况是:

  • NSNotifications有一个您定义的名称,它只是一个NSString。通知可以按名称发布,对象注册可以按名称接收通知

  • 发布通知时,可以提供notificationSender对象和/或userInfo字典。notificationSender是在接收者处理给定通知时确定谁发布了该通知的直接方法。userInfo是一个NSDictionary,可用于随通知一起提供其他上下文信息

  • 所以,您只需向NSNotificationCenter注册Worker的实例,而不是强制所有Worker采用非正式协议并在运行时使用反射式调用方法。通常,NSNotificationCenter的注册在每个工人类的init方法中完成。然后,每种类型的工作者的实例通常在NIB中设置为“冻干”对象,或者可以在应用程序委托中以编程方式实例化,以便在应用程序生命早期向通知中心注册

    当发生这种情况时,您将NSNotification发布到NSNotificationCenter(本质上是一个单例),然后注册以接收该特定类型通知的所有其他内容都将使用指定的方法来处理该类型的通知。完成后,这些方法可以在发送方上调用一个公共方法