检测异步连接何时完成

时间:2012-05-25 22:07:41

标签: iphone objective-c xcode asynchronous nsurlconnection

我有一个带有方法(getAndPlaySong)的类,它从服务器获取文本文件,从文本中获取特定字符串,并使用字符串(URL)从服务器获取音乐文件。获取文本文件的第一个服务器调用很快,所以我同步实现它。第二个需要更长时间,我想在显示时更新显示。

我希望该方法在进行之前等待异步请求完成。我试过在connectionDidFinishLoading方法中添加BOOL:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"Succeeded! Received %d bytes of data",[_receivedData length]);
    [AppDelegate playAudioWithData: _receivedData];
    _dataIsReceived = YES; //BOOL

    // release the connection, and the data object
    [connection release];
    [_receivedData release];
}

然后在getAndPlaySong方法中放入一个while循环:

[self startRequest: correctSongURL]; starts the request asynchronously

while (!_dataIsReceived) {
    //do stuff
}

结果是应用程序在到达循环时挂起。循环永远不会终止,我永远不会得到“成功...”输出。我有点困惑,并会感激一些意见。

3 个答案:

答案 0 :(得分:2)

我不希望听起来很粗鲁,但你所做的是最糟糕的事情。当然应用程序挂起,因为它有一个无限循环。即使循环最终终止,而它在循环中你的应用程序被卡住了 - 如果用户试图在你的应用程序中进行循环中途时做什么呢? 您需要改变您的思维方式,并学习如何使用状态机进行事件驱动编程。这就是iOS的范例,你必须努力做一些阅读和学习,改变你思考和构建程序的方式。

在您提出请求后,您什么都不做,即您的代码段中没有下一个代码。相反,你的应用程序坐在那里什么都不做(但仍然响应)等待连接完成(当你的应用程序什么都不做时,操作系统代表你创建了一个线程,连接代码在它内部执行,当它完成你的连接代码我们需要通知你已完成的其余代码,你可以通过代理或通过通知来完成。

这不是唯一需要等待的东西 - 如果用户点击屏幕怎么办?如果用户退出您的应用怎么办?如果 ... 您的应用需要能够响应所有可能的事件并快速响应,连接只是一个必须监听和响应的事件。如果它处于循环中,它就无法做到。

永远不要在这样的地方使用循环。

“我希望该方法在进行之前等待异步请求完成。”不,你没有 - 你在GUI的应用程序中永远不会做这样的事情。该功能必须完成执行。你需要实现一个状态机,每个iOS都是一个状态机,应用程序委托是驱动状态机的主要东西,然后你在状态之间添加更多的状态和转换,因为更多的事件被添加到程序中。

查看应用程序委托及其方法,告诉您的代码应用程序进入前台或后台,或者内存情况低等。这是事件驱动的编程,您需要扩展并构建该原则考虑您的连接事件和任何其他事件。

对不起,如果我听起来有点刺耳。

答案 1 :(得分:1)

你的应用程序挂在循环上,因为它是无限的。

在iOS上,NSURLConnectionDelegate是在连接上收到数据时获取回叫的方式,并在完成后收到通知。一切都应该通过代理异步完成。这就是在iOS上完成的方式。

流入的结果应存储在didRecieveData方法的NSData对象中。

查看NSURLConnectionDelegate上的文档,但这是一个大纲示例:

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
     int statusCode = [(NSHTTPURLResponse *)response statusCode];    
     if(statusCode == 404) {
         // Post notification and let concerned parties know something went wrong.
         [self cleanupConnection];
     }
     else if( statusCode == 200) {
         // Success do something with the data.
         requestData = [[NSMutableData alloc] init];
     }
     else {
         [self cleanupConnection];
     }
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [requestData appendData:data];
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [self finishedLoadingAppData];
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"Connection Attempt Failed with Error:%@", [error localizedDescription]);
}

答案 2 :(得分:0)

想到两个快速选项: 创建一个方法来调用以处理已完成的连接 使用NSNotification API在加载完成时发送通知

此外,您可以使用NSURLConnection didReceiveData的方法来处理从服务器递增的数据。