2012-05-25 90 views
0

我有一个类(getAndPlaySong),它从服务器获取文本文件,从文本中获取特定的字符串,并使用字符串(URL)从音乐文件中获取音乐文件服务器。第一次获取文本文件的服务器调用很快,所以我实现了同步。第二个需要更长的时间,我想在发生时更新显示。检测异步连接何时完成

我希望方法在继续之前等待异步请求完成。我试图把一个BOOL在connectionDidFinishLoading方法:

- (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]; 
} 

然后把一个while循环在getAndPlaySong方法:

[self startRequest: correctSongURL]; starts the request asynchronously 

while (!_dataIsReceived) { 
    //do stuff 
} 

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

+0

你能在while循环内显示代码吗?你想在URL加载的时候做什么?当你说,“我想更新显示的时候” - 你到底想做什么?一次性动作,还是连续的? –

+0

它是有道理的,它会挂起,你无限循环。您需要创建一个将在请求完成时触发的回调。研究使用通知系统。 – Kaili

回答

2

我不想健全粗鲁,但你做了什么是最糟糕的事情。当然,该应用程序会挂起,因为它具有无限循环。即使循环最终终止,而在循环中它的应用程序仍然卡住 - 如果用户试图在循环中间使用应用程序执行某些操作,该怎么办? 你需要改变你的想法,并学习如何在状态机中使用事件驱动编程。这就是iOS的典范,你必须指责并做一些阅读和学习,并改变你思考和构建你的程序的方式。

在您提出请求后,您什么都不做,即代码片段中未出现任何代码。相反,你的应用程序在那里没有做任何事情(但仍然是响应),等待连接完成(当你的应用程序没有做任何事情时,OS代表你创建了一个线程,连接代码在它内部执行,当它完成你的连接代码需要通知代码的其余部分已完成,例如可以通过代理或通过通知来完成此操作)。

而这并不是它需要坐下来等待的唯一东西 - 如果用户在屏幕上轻按?如果用户退出您的应用程序会怎么样?如果... 您的应用需要能够响应所有可能的事件并快速响应,连接只是一个必须监听和响应的事件。如果它在一个循环中,它不能这样做。

千万不要在这样的地方使用循环。

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

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

对不起,如果我听起来有点苛刻。

0

两个快速选项浮现在脑海中: 创建一个方法调用来处理完成的连接 使用NSNotification API发送通知的负荷完成时

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

1

你的应用挂在Loop上,因为它是无限的。

在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]); 
}