ymotov
ymotov

Reputation: 1489

iOS: CFRunLoopRun() function confusion

I've read about CFRunLoop but still a bit confused about it. I came a cross a piece of code that I'd like to clarify for myself:

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:url]]];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/xml" forHTTPHeaderField:@"Content-Type"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:postData];
[[NSURLConnection alloc]initWithRequest:request delegate:self];

CFRunLoopRun();

So, assuming this is all being called on the main thread, will it block the main thread? Or will it spawn a new thread through the CFRunLoopRun() function call?

Thanks!

Upvotes: 2

Views: 6143

Answers (2)

Rui Peres
Rui Peres

Reputation: 25917

There is actually a case where it makes sense. While creating a recursive run loop (that's what will happen when you execute that line):

It is possible to run a run loop recursively. In other words, you can call CFRunLoopRun, CFRunLoopRunInMode, or any of the NSRunLoop methods for starting the run loop from within the handler routine of an input source or timer. When doing so, you can use any mode you want to run the nested run loop, including the mode in use by the outer run loop.

So the point is to do something like this:

- (NSMutableData *)serverRequest
{
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:[NSString stringWithFormat:url]]];
    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/xml" forHTTPHeaderField:@"Content-Type"];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody:postData];
    [[NSURLConnection alloc]initWithRequest:request delegate:self];

    CFRunLoopRun();
    return _returnDataFromServer;
}

So the method serverRequest won't exit, until you actually stop the RunLoop:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    // Append the new data to the instance variable you declared
    [_connectionData appendData:data];

    CFRunLoopStop(CFRunLoopGetCurrent());
}

I wouldn't do this, it's preferable to pass this piece of work to a working thread.There are others ways to achieve the same and not use Run Loop.

Upvotes: 9

omz
omz

Reputation: 53551

Assuming this is called from the main thread, there isn't really any reason to call CFRunLoopRun, because the default run loop should already be running.

The way you're using NSURLConnection will not block the calling thread. It may spawn additional threads internally, but you don't really have to care about that. initWithRequest:delegate: will return pretty much immediately and your delegate methods will be called later (when a response is received, data is loaded, etc.).

Upvotes: 3

Related Questions