我使用“SimpleFTPSample”来执行ftp请求以列出令人振奋的信息。部分代码如下:
- (void)_startReceive
{
......
self.networkStream = (NSInputStream *) ftpStream;
self.networkStream.delegate = self;
[self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[NSTimer scheduledTimerWithTimeInterval:TIMEOUTFTP target:self
selector:@selector(dealTimeOut:) userInfo:nil repeats:NO];
......
}
我还设置了一个NSTimer来在TIMEOUTFTP之后停止networkStream,如果请求在我定义的TIMEOUTFTP中正确完成,networkStream也将被关闭。我在另一个地方使用这个方法:
- (void)downLoadData
{
NSArray* receivedData;
[ftpService _startReceive];
//wait until the network is closed
while (ftpService.isReceiving) {}
receivedData = ftpService.dataArray;
if([receivedData count] == 0) {
NSLog(@"no data get");
}
else {
NSLog(@"get data number %d", [receivedData count]);
}
}
情况是该程序停留在“while(ftpService.isReceiving){}”。我不熟悉Multiple Thread。可能是我无法正确理解运行循环。有人能告诉我为什么会这样,以及如何实现我的目的?
答案 0 :(得分:2)
在让程序继续进行之前,您应该重新考虑是否真的要等待收到的数据。相反,您应该将UI置于一种状态,即显示它正在下载并限制用户可以执行的操作,将控制权返回给应用程序的主事件循环,并让它在收到数据时调用您的委托方法。只有收到数据后,才能解锁用户界面并继续执行下一步,无论是什么。
阻止应用程序的主线程会导致糟糕的用户体验,并可能导致您的应用终止。
但是,如果你真的想这样做,你需要运行运行循环而不是忙碌的等待。类似的东西:
while (ftpService.isReceiving)
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
实际上,在你自己运行运行循环的情况下,你应该在这里和你安排流的地方使用不同的运行循环模式。默认的运行循环模式将包含来自其余框架的运行循环源,并且让那些从您自己的内部运行循环触发它们是危险的。只需使用一个任意字符串,该字符串可能对于该模式的程序是唯一的。
运行循环是各种事件和输入源(以及计时器)的集合。您的代码和框架的各个部分都将在运行循环中调度源。它们依赖于正在运行的运行循环,以便接收事件/输入/定时器触发并处理它们。通过不运行运行循环而只是忙于等待,您阻止了流从FTP连接接收数据并进行处理。