如何在继续执行下一个命令之前让程序等待异步NSURLConnection完成?

Pil*_*ast 13 web-services ios

在进入下一行代码之前,如何让我的程序等待异步NSURLConnection完成?

SetDelegate *sjd= [SetDelegate alloc];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:post delegate:sjd];
[connection start];
Run Code Online (Sandbox Code Playgroud)

这是我开始连接的方式,我处理委托中收到的数据,但我想等待连接结束,然后继续主要是因为这是在for循环中,它必须为我的数据库中的每个元素运行.

我需要将数据从手机数据库放到远程数据库中,并在数据成功放入手机数据库中的数据后删除.我正在浏览手机数据库中的每个元素并开始连接,这就是为什么我不知道如何从循环中完成下一个操作.当谈到Objective-c编程时,我是初学者,所以我不确定这是否是正确的方法

使调用同步不是一个选项,因为它会阻止程序,我有一个应该显示的进度条.

XJo*_*nes 19

你的问题有点奇怪.你不可能限制这个问题.你不能让一行代码"等待"进程完成而不阻塞某些东西,在这种情况下,循环运行的任何线程.

如果您愿意,可以使用同步调用,它不会阻止您的应用程序,它只会阻止执行它的线程.在您的示例中,您有一个循环,它不断获取远程数据,并且您希望UI在完成之前反映出来.但是你不希望你的UI被阻止.这意味着,这个带有你的循环的线程已经必须在后台线程中,这样你就可以在循环中进行同步调用,而不会阻塞你的UI线程.如果循环在UI线程上,则需要将其更改为执行所需操作.

您也可以使用异步连接执行此操作.在这种情况下,您的操作可能会实际完成更快的b/c,您可以同时处理多个请求.如果你这样做,你的循环可以保留在UI线程上,你只需要跟踪所有连接,这样当它们完成时你可以将该状态传递给相关的控制器.您需要iVars来跟踪加载状态,并在加载完成时使用协议或NSNotification进行通信.

编辑:在背景线上同步呼叫的添加示例

如果你希望循环只在所有请求完成时完全完成并且不阻止你的UI线程,这是一个简单的例子:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // post an NSNotification that loading has started
    for (x = 0; x < numberOfRequests; x++) {
        // create the NSURLRequest for this loop iteration
        NSURLResponse *response = nil;
        NSError *error = nil;
        NSData *data = [NSURLConnection sendSynchronousRequest:request
                                             returningResponse:&response
                                                         error:&error];
        // do something with the data, response, error, etc
    }
    // post an NSNotification that loading is finished
});
Run Code Online (Sandbox Code Playgroud)

无论什么对象需要显示加载状态,都应该观察并处理您在此处发布的通知.循环将在后台线程上同步并完成所有请求,并且您的UI线程将被解除阻塞并响应.这不是执行此操作的唯一方法,事实上,我会自己使用异步连接,但这是一个如何获得所需内容的简单示例.


jer*_*rts 5

如果您只是想知道它何时完成并且并不真正关心任何数据,只需使用NSNotificationCenter发布通知并让您的视图订阅它.

代表 - 完成后发布通知

-(void) connectionDidFinishLoading:(NSURLConnection*)connection {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"NSURLConnectionDidFinish" object:nil];
}
Run Code Online (Sandbox Code Playgroud)

视图 - 添加观察者并在观察时运行一些代码

-(void) viewDidLoad {

[[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(yourCleanupMethod)
                                               name:@"NSURLConnectionDidFinish"
                                              object:nil];
}

-(void) yourCleanupMethod {
    // finish up

    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您需要将一个简单的对象作为数据传回,您可以尝试在通知中加载对象参数,如下所示:

[[NSNotificationCenter defaultCenter] postNotificationName:@"NSURLConnectionDidFinish" object:yourDataObject];
Run Code Online (Sandbox Code Playgroud)

然后像这样更改您的视图和清理签名:

-(void) viewDidLoad {

// Notice the addition to yourCleanupMethod
[[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(yourCleanupMethod:)
                                               name:@"NSURLConnectionDidFinish"
                                              object:nil];
}

-(void) yourCleanupMethod:(NSNotification *)notif {
    // finish up
    id yourDataObject = [notif object];

    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
Run Code Online (Sandbox Code Playgroud)

现在我发现自己需要更多的东西,所以我最终创建了一个单身来处理我的所有请求.由于您的所有委托方法都为您提供了特定连接的NSURLConnectionDelegate实例,因此NSURLConnection您可以简单地将可变数据对象存储在字典中,并且每次都通过连接进行查找.从那里我有一个方法签名,接受和对象和选择器,我与连接关联,所以在一切已经结束后,我可以通过在该对象上执行选择器将该可变数据对象传递给请求者.

我不会在这里包含所有代码,但这可能会帮助您思考什么是可能的.我发现我在制作Web服务调用时遇到了很多代码,因此将所有内容包装在一个单例中给了我一个很好的清理方式来获取数据.希望这可以帮助!