我有一个带有方法(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
}
结果是应用程序在到达循环时挂起。循环永远不会终止,我永远不会得到“成功...”输出。我有点困惑,并会感激一些意见。
答案 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的方法来处理从服务器递增的数据。