2012-02-13 63 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

內存管理,您不會在分配後釋放您的請求或響應對象。