I use “SimpleFTPSample” to do a ftp request for listing the derictory info. Part of the code is as below:
- (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];
......
}
I also set a NSTimer to stop the networkStream after TIMEOUTFTP, the networkStream will also be closed if the request is finished correctly within TIMEOUTFTP that I define. I use the method in another place like this:
- (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]);
}
}
The situation is that the program stuck at “while (ftpService.isReceiving) {}”. I am not familiar with Multiple Thread. May be I do not understand the run loop correctly. Can someone tell me why this happen and how to achieve my purpose?
You should reconsider whether you really want to wait for the received data before letting the program proceed. Instead, you should put your UI into a state where it shows that it’s downloading and restricts what the user can do, return control to the app’s main event loop, and let it call your delegate method when data is received. Only once the data is received should you unlock the UI and proceed to the next step, whatever that is.
Blocking the main thread of the app will result in poor user experience and may get your app terminated.
If you really want to do this, though, you need to run the run loop rather than doing a busy wait. Something like:
Actually, in this case where you’re running the run loop yourself, you should use a different run loop mode both here and where you schedule the stream. The default run loop mode will contain run loop sources from the rest of the frameworks and it’s dangerous to let those fire from an inner run loop of your own. Just use an arbitrary string that’s likely to be unique to your program for the mode.
A run loop is a collection of various sources of events and inputs (and timers). Both your code and various parts of the frameworks will schedule sources in the run loop. They depend on the run loop being run in order to receive the events/inputs/timer-fires and handle them. By not running the run loop and just busy-waiting, you were preventing the stream from receiving data from the FTP connection and handling it.