2012-02-13 94 views
2

我需要对某个url进行多次https调用。因此,我做这样的事情iOS:使用performSelectorInBackground发送同步请求

//ViewController Source 
-(IBAction) updateButton_tapped { 
    [self performSelectorInBackground:@selector(updateStuff) withObject:nil]; 
} 


-(void) updateStuff { 
    // do other stuff here... 
    NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:self.url]]; 
    [request setHTTPMethod:@"POST"]; 

    NSData *postData = [[Base64 encodeBase64WithData:payload] dataUsingEncoding:NSASCIIStringEncoding]; 
    [request setHTTPBody:postData]; 

    NSURLResponse* response = [[NSURLResponse alloc] init]; 
    NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil]; 

    //Process the recieved data... 

    //Setup another synchronous request 
    data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil]; 

    //Process data 

    //do this another 4 times (note for loop cannot be use in my case ;)) 

    //Finally update some view controllers 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationIdentifier" object:self]; 
} 

所以这个代码的问题是,它随机崩溃(并不总是频繁)。日志中没有调试输出。有时我的整个应用程序冻结,或者只是崩溃了整个程序。但是如果我在主线程上运行它,它永远不会崩溃。因此,我认为代码是正确的,我想现在它与iphone上的线程有关。

以这种方式运行代码时会发生什么问题,以及可能导致随机崩溃的原因?

回答

0

控制器或任何可能假设他们正在主线程上接收通知,在你的情况下,他们不(这并不是一个安全的假设)。他们有没有做任何事情之前,数据/更新的UIKit东西控制器派遣回主线程中的通知回调等

你也应该把一个@autorelease块在你的-updateStuff整个实施。

这里有一个回调通知的例子,你可能会收到你的控制器之一:

- (void)updateStuffNotificaiton:(NSNotification*)note 
{ 
    // Can't assume we're on the main thread and no need to 
    // test since this is made async by performSelectorInBacground anyway 
    dispatch_async(dispatch_get_main_queue(), ^{ 
    // relocate all your original method implementation here 
    }); 
} 

还要注意的是,如果你的-updateStuff实现创建和操纵数据结构您的通知回调方法,然后访问时,对于妥善保护访问者非常重要。将数据批发传递回通知userInfo字典中的回调通常会更好。

将自动释放符号您-updateStuff方法的一个例子:

-(void) updateStuff 
{ 
@autoreleasepool { 
    // do other stuff here... 
    NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:self.url]]; 
    [request setHTTPMethod:@"POST"]; 

    // rest of method snipped for brevity 

    //Finally update some view controllers 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationIdentifier" object:self]; 
} 
} 
+0

感谢您的回答。但我如何在我的情况下使用autorelease块。我不知道autorelease附加。 – toom 2012-02-13 17:30:26

+0

@toom当你在后台线程上执行时,你需要一个自动释放池。你的选择是将调度切换到为你管理这个池的Grand Central Dispatch,或者简单地把方法的主体放在'@ autoreleasepool'块中。我已经为你回答了后者的一个例子。 – 2012-02-13 17:56:30

+0

谢谢你的帮助。 – toom 2012-02-13 20:25:59

0

请重新检查你的代码,这样你就不会更新后台线程任何GUI。另外,使用异步处理应该更好。

1

内存管理,您不会在分配后释放您的请求或响应对象。