iPhone头痛 - 线程,通知和URL异步连接

时间:2011-07-15 14:59:34

标签: iphone multithreading asynchronous notifications nsurlrequest

一些代码而不是很长的解释。 问题是:

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 :(得分:0)

从您提供的代码中,通知是从另一个线程发布的,而不是您注册观察者的主线程。

Apple's Notification Documentation中,它说

  

在多线程应用程序中,通知始终在发布通知的线程中传递,这可能与观察者注册的线程不同。

你可以做的是将通知移动到它自己的方法中,然后像这样使用performSelectorOnMainThread:

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