Головная боль iPhone - потоки, уведомления и асинхронные соединения URL - PullRequest
0 голосов
/ 15 июля 2011

Некоторый код вместо длинного объяснения.Проблема:

При вызове из viewDidLoad серверный вызов вызывает методы делегатов (connectionDidFinishLoading и т. Д.).Но при вызове из XMLFileFullParsed запрос запускается на сервер, но те же методы не запускаются.

Если я вызываю [self loadXMLDatas] вместо потоков, то оба вызова сервера работают нормально.

Почему?

Я начинаю здесь:

- (void)viewDidLoad {
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(foundaTag:) name:@"foundaTag" object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(XMLFileFullParsed:) name:@"XMLFileFullParsed" object:nil];

    self.server = [[ServerCommManager alloc] initWithServer:@"http://someserver/"];
    [self.server sendQuestionWithCallIdentifier:@"IDENTIFIER" onPage:@"testpage.php" withParams:nil sendAnswerToObject:self];  // -- This one works 

    [NSThread detachNewThreadSelector:@selector(loadXMLDatas) toTarget:self withObject:nil];
}

- (void) loadXMLDatas {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
Do things, create a XMLparser, start to parse.
[pool release];
}

- (void) XMLFileFullParsed:(NSNotification*)notification {

    [self.server sendQuestionWithCallIdentifier:@"IDENTIFIER" onPage:@"testpage.php" withParams:nil sendAnswerToObject:self]; // -- This one doesn't work
}

XMLParser.m

- (void) doYourJob {
    [self doTheJob];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"XMLFileFullParsed" object:nil userInfo:nil];
}

- (void) doTheJob:(XMLTag*)tag {
    if ([tag.name isEqualToString:@"searchedtag"]) {
       theData = extract some datas
       [[NSNotificationCenter defaultCenter] postNotificationName:@"foundaTag" object:self userInfo:[NSDictionary dictionaryWithObject:theData forKey:@"data"]];
        return;
    }

    for (XMLTag* aTag in tag.childtags) {
        [self doTheJob:aTag];
    }
}

Глубоко внутри сервера comm.m

- (void) executeRequest  {
   some init
self.connection = [NSURLConnection connectionWithRequest:urlRequest delegate:self];
}

- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response  {

}

- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data  
{

}

- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error 
{

}

- (void)connectionDidFinishLoading:(NSURLConnection*)connection 
{

}

1 Ответ

0 голосов
/ 15 июля 2011

Из кода, который вы указали, уведомление отправляется из другого потока, а не из основного потока, в котором вы зарегистрировали наблюдателя.

В Документация Apple по уведомлению , оноговорит

В многопоточном приложении уведомления всегда доставляются в потоке, в котором было опубликовано уведомление, что может не совпадать с тем, в котором наблюдатель зарегистрировался.

Что вы можете сделать, это переместить уведомление в его собственный метод, а затем использовать executeSelectorOnMainThread, например, так:

- (void) doTheJob:(XMLTag*)tag {
    if ([tag.name isEqualToString:@"searchedtag"]) {
       theData = extract some datas
       [self performSelectorOnMainThread:@selector(sendNotification:) withObject:theData waitUntilDone:YES];
        return;
    }

    for (XMLTag* aTag in tag.childtags) {
        [self doTheJob:aTag];
    }
}

- (void)sendNotification:(NSArray *)theData {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"foundaTag" object:self userInfo:[NSDictionary dictionaryWithObject:theData forKey:@"data"]];
}
...