0

我在寫一個應用程序,它利用UITabBarController切換視圖。一個選項卡使Web請求收集並在填充UITableView之前處理JSON數據。我試圖在後臺加載這些數據,所以當用戶按下這個標籤時,表格就不會出現延遲。將顯示一個ActivityIndi​​cator,然後該表將加載數據。在UITabViewController中使用dispatch_sync檢索數據

每個請求都被製作,處理並放置在一個NSMutableArray中,然後將其排序並添加到UITableView中。

當我使用dispatch_sync時,數據被加載並且數組被創建並呈現正常,但是視圖的UI被阻止加載。我在想,因爲某些原因,我沒有把這個查詢傳給後臺隊列。如果我使用dispatch_async,那麼在嘗試訪問主線程上的NSMutableArray時會收到異常。

所以,我的問題是允許用戶切換到包含此TableView的選項卡的適當模式,在數據加載和處理(在後臺)時顯示一個ActivityIndi​​cator,然後一旦完成,UITableView是加載處理的數據。從的UITableViewController

Relavent代碼:

#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 

    currentLat = appDelegate.currentLatitude; 
    currentLong = appDelegate.currentLongitude; 

    finalDistanceArray = [[NSMutableArray alloc] init]; 

    [self compareLocationMMC]; 
    [self compareLocationLVMC]; 
    [self compareLocationSBCH]; 
    [self compareLocationGVCH]; 
    [self compareLocationSYVCH]; 

    NSSortDescriptor *lowestToHighest = [NSSortDescriptor sortDescriptorWithKey:@"distance" ascending:YES]; 

    [hospitalList sortUsingDescriptors:[NSArray arrayWithObject:lowestToHighest]]; 

} 

- (void)compareLocationMMC { 


NSString * searchURL = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=true", currentLat.floatValue, currentLong.floatValue, MMC_LAT, MMC_LON]; 
NSURL * myURL = [NSURL URLWithString:searchURL]; 

dispatch_sync(kBgQueue, ^{ 
    NSData* data = [NSData dataWithContentsOfURL: 
        myURL]; 
    [self performSelectorOnMainThread:@selector(fetchedData:) 
          withObject:data waitUntilDone:YES]; 
}); 


} 
//The compareLocationXXX method is repeated 4 more times with different search strings 

- (void)fetchedData:(NSData *)responseData { 

//parse out the json data 
NSError* error; 
NSDictionary* json = [NSJSONSerialization 
         JSONObjectWithData:responseData 

         options:kNilOptions 
         error:&error]; 

NSArray* stationDistance = [json objectForKey:@"routes"]; 

NSDictionary* legs = [stationDistance objectAtIndex:0]; 

NSArray* legsBetween = [legs objectForKey:@"legs"]; 

NSDictionary* distanceBetween = [legsBetween objectAtIndex:0]; 

finalDistance = [distanceBetween valueForKeyPath:@"distance.text"]; 

[finalDistanceArray addObject:finalDistance]; 

} 

回答

0

Dispatch_sync()實際上會阻塞線程它是從,因爲它暫停執行入隊塊調用。 Dispatch_async是一個更好的選擇,因爲它允許恢復調用功能。您可以將一個調用包裝在另一個調用中,以允許您在主線程上執行完成代碼。這也使得代碼執行非常容易閱讀。

// Turn on status bar spinner, for example 
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 
dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
    // Do background stuff here 
     .... 
    NSData* data = [NSData dataWithContentsOfURL:myURL]; 
    // used parsed data to populate data structure of some type 
     .... 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // Use background stuff here 
     [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 
    }); 
}); 

雖然像NSURLConnection回調基於API可能是最好的網絡負載,這會工作得相當好。特別是對於小的請求。

+0

謝謝!我相信我在後臺工作正常,但隨後的代碼訪問NSMutableArray並在數據加載之前這樣做導致異常。我如何等待以確保數據在訪問之前被加載和排序? – blueHula 2012-02-15 19:57:05

+0

在「使用背景資料」部分之前,您不應使用您加載的數據。這可能會複製您獲取的數據並調用'reloadTable' [我發佈的這個答案與您的新問題有關。](http://stackoverflow.com/a/8962406/927947) – NJones 2012-02-16 04:35:09