iOS: путаница с функцией CFRunLoopRun()

Я читал о CFRunLoop, но все еще немного смущен этим. Я наткнулся на кусок кода, который я хотел бы уточнить для себя:

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();

Итак, предположим, что все это вызывается в основном потоке, заблокирует ли он основной поток? Или он создаст новый поток через вызов функции CFRunLoopRun()?

Спасибо!

2 ответа

Решение

Предполагая, что это вызывается из основного потока, нет никаких причин для вызова CFRunLoopRunпотому что цикл запуска по умолчанию уже должен быть запущен.

То, как вы используете NSURLConnection не будет блокировать вызывающий поток. Это может порождать дополнительные потоки внутри, но вам не нужно об этом беспокоиться. initWithRequest:delegate: вернется в значительной степени сразу, и ваши методы делегата будут вызваны позже (когда ответ получен, данные загружены и т. д.).

На самом деле есть случай, когда это имеет смысл. При создании рекурсивного цикла выполнения (вот что произойдет, когда вы выполните эту строку):

Возможно выполнить цикл выполнения рекурсивно. Другими словами, вы можете вызвать CFRunLoopRun, CFRunLoopRunInMode или любой из методов NSRunLoop для запуска цикла выполнения из подпрограммы обработчика входного источника или таймера. При этом вы можете использовать любой режим, в котором хотите запустить вложенный цикл выполнения, включая режим, используемый внешним циклом выполнения.

Итак, дело в том, чтобы сделать что-то вроде этого:

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

Так что метод serverRequest не выйдет, пока вы действительно не остановите RunLoop:

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

    CFRunLoopStop(CFRunLoopGetCurrent());
}

Я бы не стал этого делать, предпочтительно передать эту часть работы в рабочий поток. Существуют другие способы добиться того же и не использовать Run Loop.

Другие вопросы по тегам