2010-06-28 74 views
8

最多的iOS 3.2,我用這種代碼在後臺加載UIImageView圖像,它工作得很好......的iOS4及背景的UIImage setImage:]

代碼:

- (void)decodeImageName:(NSString *)name 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    UIImage *newImage = [UIImage imageNamed:name]; 
    [myImageView setImage:newImage]; 
    [pool release]; 
} 
... 
[self performSelectorInBackground:@selector(decodeImageName:) withObject:@"ID"] 

。 ..即使[UIImageView setImage:]不是線程安全的!

但是自iOS 4以後,它不再工作了......圖像在setImage調用後兩秒鐘出現在屏幕上。如果我執行的是[myImageView performSelectorOnMainThread:@selector(setImage:) withObject:newImage waitUntilDone:YES]而不是[myImageView setImage:newImage],圖像立即顯示,但似乎在運行過程中又被重新解碼(忽略之前的[UIImage imageNamed:],它應該已經解碼了圖像數據),導致我的主線程暫停。 。即使文檔說底層圖像緩存在所有線程之間共享。

有沒有想法?

+0

您好,感謝您提出這個問題。我想知道爲什麼它現在不適用於我的應用程序。 – GeneCode 2013-03-27 14:26:22

回答

3

performSelectorInBackground:在後臺線程中運行選擇器。然而,setImage:是一個UI功能。 UI函數只能在主線程上運行。我沒有洞察到特定的問題,但這是對代碼的直覺,也可能是iOS4處理在後臺線程中運行UI函數的(不支持的)機制。

4

不要在後臺做!它不是線程安全的。由於一個UIImageView也是NSObject,我認爲,它使用-[performSelectorOnMainThread:withObject:waitUntilDone:]可能的工作,如:

[myImageView performSelectorOnMainThread:@selector(setImage:) withObject:newImage waitUntilDone:NO]; 

而且這UIImage這是新線程安全的。 UIImageView仍然不是線程安全的。

+1

嗨Evadne,你在哪裏讀過UIImage是線程安全的?在任何地方都找不到。 – jasongregori 2011-10-26 21:52:22

1

如果你使用iOS 4.0,你應該真的考慮閱讀塊和GCD。使用這些技術,您只需更換你的方法有:

- (void)decodeImageName:(NSString *)name 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    UIImage *newImage = [UIImage imageNamed:name]; 

    dispatch_async(dispatch_get_main_queue(), ^{ 
     [myImageView setImage:newImage]; 
    } 

    [pool release]; 
} 
+0

它沒有多大幫助。 dispatch_async仍然會暫停主線程的時間超過應該重新解碼uiimage的時間。我如何確定UIImage在[UIImage imageNamed:name]之後被解碼? – 2010-06-28 10:02:39

+0

我會推薦支持OS 3.1.3至少幾個月,以及3.2版,直到4.0+ for iPad發佈後的幾個月。 – 2010-06-28 16:00:37

1

讓我們的座右銘:

@property(nonatomic, readonly) CGImageRef CGImage

討論

如果圖像數據已被清除,因爲內存約束,調用此方法將強制將數據加載回內存。重新加載圖像數據可能會導致性能損失。

因此,您可能只需致電image.CGImage即可。我不認爲CGImages是懶惰的。

如果不工作,你可以強制的東西渲染像

// Possibly only safe in the main thread... 
UIGraphicsBeginImageContext((CGSize){1,1}); 
[image drawInRect:(CGRect){1,1}]; 
UIGraphicsEndImageContext(); 

有人警告線程安全。該文檔說UIGraphics{Push,Pop,GetCurrent}Context()是主線程,但沒有提及任何有關UIGraphicsBeginImageContext()。如果您擔心,請使用CGBitmapContextCreateCGContextDrawImage