0

所以,顯然我在這裏做錯了什麼。我有一個使用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更合適,但顯然我對操作隊列缺乏透徹理解是一個問題。

將此背景操作放置在模型類中可能存在任何問題嗎?後臺操作是否總是在控制器類中?還有什麼我在這裏做錯了嗎?

回答

1

問題是你沒有保留gaugeDownloadQueue。所以它只是在一陣煙霧中消失,一切都發生在主線上。 (你不會可以取消任何東西,因爲你沒有提到任何操作隊列。)

你需要一個持久的參考(例如一個實例變量/屬性)保留gaugeDownloadQueue。否則,對你來說,這是無用的,以多種方式。

此外,你的AFHTTPRequestOperation完成塊被調用什麼線程?如果它是後臺線程,並且您正在爲界面做些什麼(例如,您撥打updateGaugeTable,那肯定會造成麻煩)。你使用NSOperation的事實根本不能解除你擔心自己在線的責任。

+0

下面是如何使用的NSOperation/NSOperationQueue使在後臺事情發生的例子:https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch25p865mandelbrotOperation/ch38p1106mandelbrotNoThreading/MyMandelbrotView.m – matt 2014-08-29 16:19:39

+0

這是有道理的,但它似乎仍然阻止主線程。在服務調用返回之前,UI仍然沒有響應。 – Pheepster 2014-08-29 16:32:52

+0

好的,但是你正在使用一些我一無所知的非可可類(例如AFHTTPRequestOperation),那麼我怎麼知道你不會濫用它們呢?例如,你在AFHTTPRequestOperation上有一個完成塊 - 但是我怎麼知道被調用的線程?如果它是後臺線程,並且你正在爲界面做些什麼,那肯定會造成麻煩。 – matt 2014-08-29 16:52:47