NSURLCПодключение делегирования и потоков - iPhone - PullRequest
3 голосов
/ 01 августа 2009

У меня есть класс, который обновляет два файла .plist в каталоге документов приложения через NSURLConnection. Класс действует как собственный делегат для NSURLConnection. Он работает правильно, когда я запрашиваю один файл, но не удается, когда я пытаюсь обновить два файла. Похоже, я должен начать новый поток для каждого из сообщений getNewDatabase?

- (void)getAllNewDatabases {
    [self performSelectorOnMainThread:@selector(getNewDatabase:) withObject:@"file1" waitUntilDone:YES];
    [self performSelectorOnMainThread:@selector(getNewDatabase:) withObject:@"file2" waitUntilDone:YES];
}

- (BOOL)getNewDatabase:(NSString *)dbName
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSMutableString *apiString = [[NSMutableString alloc] initWithString:kAPIHost];
    [apiString appendFormat:@"/%@.plist",dbName];
    NSURLRequest *myRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:apiString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
    NSURLConnection *myConnection = [[NSURLConnection alloc] initWithRequest:myRequest delegate:self];
    [apiString release];
    if( myConnection )
    {
        //omitted for clarity here
    }
    [pool release];
}
//NSURLConnection delegate methods here ...

Ответы [ 2 ]

8 голосов
/ 01 августа 2009

Я нашел кое-что интересное с NSURLConnection и NSThread - поток будет жить столько времени, сколько потребуется для выполнения метода, который вы вызываете из него.

В приведенном выше случае поток будет жить только столько времени, сколько требуется для завершения getNewDatabase:(NSString *)dbName, поэтому убивает любой из его методов-делегатов, прежде чем они действительно успеют что-либо сделать.

Я нашел этот веб-сайт, который дает лучшее объяснение и решение проблемы

Я немного подправил его, чтобы у меня было время ожидания, если оно не завершилось в заданный период времени (удобно, когда кто-то ходит между точками доступа)

    start = [NSDate dateWithTimeIntervalSinceNow:3];

    while(!isFinished && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
                                                  beforeDate:[NSDate distantFuture]]){

    if([start compare:[NSDate date]] == NSOrderedAscending){
        isFinished = YES;
    }
}
4 голосов
/ 01 августа 2009

В текущем коде, который вы указали, getNewDatabase: работает в главном потоке вашего приложения. В этом конкретном случае проблема заключается не в жизненном цикле нити, как заметил Джеймс в своем случае.

Если вы намеревались выполнить эту операцию в фоновом режиме, я бы рекомендовал использовать NSOperationQueue и NSOperation, а не решать проблему с текущим кодом. Я думаю, что ваш случай отлично подходит для NSOperationQueue, особенно если учесть, что вам нужно выполнить более одной задачи загрузки.

У Дэйва Дрибина есть отличная статья об использовании асинхронного API, такого как NSURLConnection, внутри NSOperation. В качестве альтернативы, пока вы работаете в фоновом потоке, вы также можете упростить процесс и просто использовать вместо этого в своей NSOperation синхронный метод API, например initWithContentsOfURL:.

Маркус Зарра также написал учебное пособие , которое демонстрирует, как легко включить и использовать NSOperationQueue для простых фоновых операций.

...