在 iPhone 应用初始化时进行多次服务调用

Posted

技术标签:

【中文标题】在 iPhone 应用初始化时进行多次服务调用【英文标题】:Making multiple service calls on iPhone app initialization 【发布时间】:2010-09-02 21:48:40 【问题描述】:

我需要在应用程序中进行多个异步服务调用:didFinishLaunchingWithOptions: 来自我的应用程序委托的方法,以便从服务中检索一些数据,以便在我的应用程序中的各种控制器中使用。我可以控制服务,并且我将 API 设计为尽可能 RESTful,因此我需要在应用初始化期间进行多次调用。

我想要做的是显示一个带有进度指示器的加载视图 - 类似于 Default.png 中的默认初始屏幕 - 并在服务调用完成并且我有我需要的初始值后删除该视图。如果只有一个服务调用,这很容易做到,因为我可以简单地将该逻辑挂钩到 NSURLConnection 的 connectionDidFinishLoading: 委托方法中,方法是隐藏加载视图并显示根控制器。

但是,对于多个服务调用,它变得很棘手。我可以将所有内容“链接”在一起并触发一个请求,等待它完成/失败,然后触发第二个请求,依此类推,直到我到达最后一个请求。在最后一个请求中,然后我隐藏加载视图并显示普通视图。但是,这可能会因多次服务调用而变得笨拙,并且代码变得难以理解和遵循。

对此有最佳方法的建议吗?

我认为一种解决方案是让一个单例类负责进​​行服务调用和应用程序初始化。单例对象将在启动时并行触发所有必要的请求,并且每个失败/完成回调将检查每个请求是否已完成。如果所有请求都完成了,那么它可以调用应用程序委托中的某个方法并告诉它隐藏加载视图、显示根控制器等。

想法?

【问题讨论】:

【参考方案1】:

另一种可能性是让每个服务完成回调通知(NSNotification)进度指示器的控制器已经取得了进展。您还可以告诉进度指示器的控制器您计划发出多少个请求,并让它记分,当它认为一切都完成时,它自己会进行回调。

【讨论】:

这样您可以一次启动所有服务请求,而不是通过序列化它们来减慢速度。 谢谢。这或多或少是我采用的方法,因为我只有几个请求并且只需要一个轻量级的解决方案。每个完成的请求都会通知主对象一个请求已经完成,并且该主对象将在加载主应用程序视图之前检查是否所有必需的请求都已完成。【参考方案2】:

我正在使用 NSOperationQueue 做类似的事情,该 NSOperationQueue 被配置为一次只运行 1 个操作。参见例如WeaveEngine.m 它是synchronizewithServer:credentials: 方法。我将所有单独的操作排队,这些操作大多是异步网络调用。

【讨论】:

【参考方案3】:

你可以使用 NSThreading 并在单独的线程中为你需要得到的每件事进行同步调用

[NSThread detachNewThreadSelector:@selector(getDataRequest1:) toTarget:self withObject:urlRequest];
[NSThread detachNewThreadSelector:@selector(getDataRequest2:) toTarget:self withObject:urlRequest];
[NSThread detachNewThreadSelector:@selector(getDataRequest3:) toTarget:self withObject:urlRequest];

然后在每个线程的选择器中执行类似

的操作
- (void) getDataRequest1:(NSURLRequest*)urlRequest 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSHTTPURLResponse *urlResponse;
    NSError *error;
    NSData *responseData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&urlResponse error:&error];
    NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
    if ([urlResponse statusCode] < 200 || [urlResponse statusCode] > 299) 
        //request probably failed
    else
        [self performSelectorOnMainThread:@selector(completeRequest1:) withObject:responseData waitUntilDone:NO];           
    
    [pool drain];
    [responseString release];
    [urlRequest release];   

当然,这实际上取决于您想要产生多少请求/线程。 并且您需要跟踪生成的数量与完成的数量,以便正确停止旋转器。

【讨论】:

以上是关于在 iPhone 应用初始化时进行多次服务调用的主要内容,如果未能解决你的问题,请参考以下文章

调用外部服务器时,有异常就进行多次调用

当我从 iPhone 中删除应用程序时,是不是可以调用网络服务?

onLocationChanged 在应用程序启动时被多次调用

iPhone Web 服务通过证书身份验证调用 WCF 服务

iPhone 应用程序在请求定位服务权限时崩溃

如何使用不同的方法多次模拟调用 AWS 服务的 Golang 函数的单元测试?