簡體   English   中英

在objective-c中正確的多線程方式?

[英]Correct way to multithread in objective-c?

我有一個顯示圖像的UITableView。 每個單元格都有一個圖像,每次加載一個單元格時,我在后台調用一個選擇器(來自cellForRowAtIndexPath),如下所示:

[self performSelectorInBackground:@selector(lazyLoad:) withObject:aArrayOfData];

唯一的問題是,有時我會遇到崩潰(因為我正在嘗試在其他地方讀取時在后台更改數據)。 這是錯誤:

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <CALayerArray: 0xce1a920> was mutated while being enumerated.'

在后台更新數據時,是否應將其移至主選擇器並進行更改? 或者我應該以不同方式調用@selector()?

謝謝!

如果您可以將操作留在主線程上並且沒有任何問題,也不會出現問題。

但是:讓我們假設你已經做到了並遇到問題。 答案是:不要延遲加載中修改數組。 切換到主線程來修改數組。 請參閱Brad的答案:

https://stackoverflow.com/a/8186206/8047

對於使用塊來實現它的方法,所以你可以將你的對象發送到主隊列(你可能也應該首先使用GCD來調用延遲加載,但這不是必需的)。

您可以使用@synchronized塊來防止線程相互走過。 如果你這樣做

@synchronized(array)
{
  id item = [array objectAtIndex:row];
}

在主線程和

@synchronized(array)
{
  [array addObject:item];
}

在后台,你保證他們不會在同一時間發生。 (希望你可以從那里推斷到你的代碼 - 我不確定你在那里用陣列做什么..)

但是,似乎你必須通知主線程你已經加載了一個單元格的數據(通過performSelectorOnMainThread:withObject:waitUntilDone :,比如說),那么為什么不傳遞數據呢?

鑒於術語“延遲加載”,我假設這意味着您要從服務器中提取圖像。 (如果圖像是本地的,則實際上不需要多線程)。

如果您從服務器下載圖像,我建議使用這些內容(使用ASIHTTPRequest

   static NSCache *cellCache; //Create a Static cache

    if (!cellCache)//If the cache is not initialized initialize it
    {
        cellCache = [[NSCache alloc] init];
    }
    NSString *key = imageURL;
    //Look in the cache for image matching this url
    NSData *imageData = [cellCache objectForKey:key];

    if (!imageData)
    {
        //Set a default image while it's loading
        cell.icon.image = [UIImage imageNamed:@"defaultImage.png"];'

        //Create an async request to the server to get the image
        __unsafe_unretained ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:imageURL]];


        //This code will run when the request finishes
        [request setCompletionBlock:^{
            //Put downloaded image into the cache
            [cellCache setObject:[request responseData] forKey:key];
            //Display image
            cell.icon.image = [UIImage imageWithData:[request responseData]];
        }];
        [request startAsynchronous];
    }
    else 
    {
        //Image was found in the cache no need to redownload
        cell.icon.image = [UIImage imageWithData:imageData];
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM