所以,顯然我在這裏做錯了什麼。我有一個使用MVC的應用程序,並且在我的一個模型類中,我調用了可能需要一些時間處理的Web服務。視圖控制器調用啓動下載過程的模型類中的方法。下載過程通過放置在NSOperationQueue中的AFHTTPRequestOperation執行。整個下載過程發生在視圖控制器之外的模型類中。但是,下載操作似乎會阻止主線程,因爲UI在操作過程中無響應。我已經硬編碼暫停模擬慢速網絡。當操作完成時,它通過委託方法調用視圖控制器。此代碼有效,但正如我所提到的,它阻止了主線程。NSoperationQueue阻塞主線程
在我的模型類(StreamGauge)我有以下幾點:
-(void)getGaugeReadings{
NSString *endpointURL = [NSString stringWithFormat:@"http://...", stationID_, timeSpan_];
NSURL *url = [NSURL URLWithString:endpointURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject){
NSData *data = (NSData*)responseObject;
[self processXmlObject:data];
[self setGaugeFlowKeys:[self getFlowKeys]];
[NSThread sleepForTimeInterval:3];
[self.delegate updateGaugeTable];
}failure:^(AFHTTPRequestOperation *operation, NSError *err){
NSLog(@"ERROR: %@", [err localizedDescription]);
}];
NSOperationQueue *gaugeDownloadQueue = [[NSOperationQueue alloc] init];
[gaugeDownloadQueue setName:@"Gauge_Download"];
[gaugeDownloadQueue addOperation:operation];
}
在我的視圖控制器我已經在我的viewDidLoad以下(含硬編碼參數):
- (void)viewDidLoad
{
[super viewDidLoad];
gauge = [[StreamGauge alloc] initWithStationID:@"A3185AX400" forTimeSpan:24];
[gauge setDelegate:self];
[gauge getGaugeReadings];
}
我更習慣於像這樣使用GCD,但現在我需要在超時過期後取消操作的能力,所以NSOperationQueue更合適,但顯然我對操作隊列缺乏透徹理解是一個問題。
將此背景操作放置在模型類中可能存在任何問題嗎?後臺操作是否總是在控制器類中?還有什麼我在這裏做錯了嗎?
下面是如何使用的NSOperation/NSOperationQueue使在後臺事情發生的例子:https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch25p865mandelbrotOperation/ch38p1106mandelbrotNoThreading/MyMandelbrotView.m – matt 2014-08-29 16:19:39
這是有道理的,但它似乎仍然阻止主線程。在服務調用返回之前,UI仍然沒有響應。 – Pheepster 2014-08-29 16:32:52
好的,但是你正在使用一些我一無所知的非可可類(例如AFHTTPRequestOperation),那麼我怎麼知道你不會濫用它們呢?例如,你在AFHTTPRequestOperation上有一個完成塊 - 但是我怎麼知道被調用的線程?如果它是後臺線程,並且你正在爲界面做些什麼,那肯定會造成麻煩。 – matt 2014-08-29 16:52:47