2010-05-30 53 views
0

我有一個UIViewController,並且在該控制器中,我從URL源獲取圖像。該圖像在單獨的線程中獲取,之後在主線程上更新用戶界面。此控制器顯示爲UIScrollView父級中的頁面,該父級實施該控制器以釋放不再可見的控制器。iPhone:在多線程環境中釋放UIViewController的問題

當線程在釋放UIViewController之前完成獲取內容時,一切正常 - 但是當用戶在線程完成之前滾動到另一個頁面時,控制器將被釋放,並且控制器的唯一句柄由線程擁有控制器的releaseCount等於1。現在,只要線程水渠NSAutoreleasePool,控制器得到釋放,因爲releaseCount變爲0。在這一點上,我的應用程序崩潰,並且我收到以下錯誤消息:

布爾_WebTryThreadLock (bool),0x4d99c60:試圖從主線程或Web線程以外的線程獲取Web鎖。這可能是從輔助線程調用UIKit的結果。現在崩潰...

回溯顯示應用程序在[super dealloc]調用時崩潰,並且它總是有意義的,因爲dealloc函數在池被耗盡時必須由線程觸發。我的問題是,我如何克服這個錯誤並釋放控制器而不會泄漏內存? ,我試圖

的一個解決方案是調用[自我保留]池之前被排出,以便retainCount不下降到零,然後使用下面的代碼在主線程以釋放控制器:

[self performSelectorOnMainThread:@selector(autorelease) 
    withObject:nil waitUntilDone:NO]; 

不幸的是,這並沒有奏效。下面是一個線程執行的功能:

- (void)thread_fetchContent { 

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    NSURL *imgURL = [NSURL URLWithString:@"http://www.domain.com/image.png"]; 

    // UIImage *imgHotspot is declared as private - The image is retained 
    // here and released as soon as it is assigned to UIImageView 

    imgHotspot = [[[UIImage alloc] initWithData: 
     [NSData dataWithContentsOfURL: imgURL]] retain]; 

    if ([self retainCount] == 1) { 

     [self retain]; // increment retain count ~ workaround 
     [pool drain]; // drain pool 

     // this doesn't work - i get the same error 

     [self performSelectorOnMainThread:@selector(autorelease) 
      withObject:nil waitUntilDone:NO]; 
    } 

    else { 

     // show fetched image on the main thread - this works fine! 

     [self performSelectorOnMainThread:@selector(showImage) 
      withObject:nil waitUntilDone:NO]; 

     [pool drain]; 
    } 
} 

請幫幫忙!先謝謝你。

回答

0

是的,它可以真的讓人望而生畏,試圖保持線程化的東西同步。 您描述的用例對於NSOperation來說聽起來很完美。 通過使用這種方法,您可以在控制器中擁有一個NSOperationQueue作爲ivar,並在控制器的dealloc方法中釋放它。

好處很多,當控制器視圖在scrollView中可見時,它(viewWillAppear或loadView)開始使用添加到NSOperationQueue的NSOperation檢索圖像,如果用戶在操作完成之前滾動離開,NSOperationQueue被釋放後,它會照顧發送一個取消信息給所有的操作,並且通常以有序的方式關閉所有的操作。

如果這是您的應用程序中的一箇中心組件,我想這是因爲您將想法釋放到「屏幕」的東西之後,我會建議讓您的控制器在loadVIew方法中顯示「虛擬圖像」,並然後在viewDidLoad中開始提取操作。你可以繼承NSOperation,這樣你就可以發送URL並讓它做它的事情。

幾周前我做了類似的事情,我必須不斷地開始線程化操作,但是很有可能用戶會做一些事情導致這些操作被取消。該功能是「構建」到NSOperation中的。 NSOperation question

+0

謝謝! NSOperation方法非常有幫助 - 我查看了您提供的鏈接以及http://www.cimgf上的教程。com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/- 它解決了我的問題:) – 2010-05-30 14:22:20