iOS:sendSeynchronousRequest with performSelectorInBackground

时间:2012-02-13 17:07:17

标签: ios multithreading httprequest

我需要对某个网址进行几次https调用。所以我做这样的事情

//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上的线程有关。

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

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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];
 }
}

答案 2 :(得分:0)

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