2011-11-04 29 views
1

在我正在開發的應用程序中,我有一個水平的UIScrollView用作一種表格視圖。使用GCD添加UIViews

向它添加子視圖會阻塞主線程,所以我決定改用GCD,並在後臺線程中創建視圖並將它們添加到主隊列中的UIScrollView實例。

相關的代碼是這樣的:

NSUInteger numberOfItems = [_dataSource numberOfItemsInBandView:self]; 
CGFloat __block nextX = 0.0; 

dispatch_queue_t bgQueue = dispatch_queue_create("bandview", NULL); 

for (NSUInteger i = 0; i < numberOfItems; i++) { 
    dispatch_async(bgQueue, ^{ 
     UIView *itemView = [_dataSource bandView:self viewForItemAtIndex:i]; 
     itemView.frame = CGRectMake(nextX, 0, itemView.frame.size.width, itemView.frame.size.height); 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [_scrollView addSubview:itemView]; 
      _scrollView.contentSize = CGSizeMake(nextX, self.frame.size.height); 
     }); 
     nextX += itemView.frame.size.width; 
    }); 
} 

dispatch_release(bgQueue); 

_scrollViewUIScrollView實例(正確初始化)。

我期望的是將子視圖逐個添加到UIScrollView,但是我所遇到的情況是所有內容都異步運行,然後滾動條會刷新並立即添加所有子視圖(這是不是我所期望的)。

任何人都可以發現我在這裏失蹤的東西嗎?

+0

我認爲你正在做的事情沒問題,視圖被創建並很快添加到滾動視圖中。如果您可以指定延遲,則可以嘗試使用dispatch_after將您的調度封裝到main的測試。另外,正如其他人所建議的那樣,您可能想爲您的後臺隊列使用全局併發隊列 – timthetoolman

回答

3

UI需要在主線程上進行更改。執行UI後臺線程(異步gcd隊列)中的更改將導致您看到的未定義/不受歡迎的行爲。添加子視圖似乎不太可能是問題的主要原因。問題可能在於爲子視圖檢索數據的方式。解決方案是添加所有的子視圖,然後異步地爲它們檢索數據,然後在操作完成時更新它們。另外考慮不要添加用戶不可見的視圖,並且在用戶滾動時類似於UITableView的工作方式動態添加視圖。

+0

我認爲'dispatch_get_main_queue'在主線程中運行。情況並非如此嗎?我添加了一個'NSAssert'來檢查它,並且它沒有失敗... – pgb

+0

啊,我看到它們被添加回主線程,但有可能所有或大量視圖都排隊進入相同的主運行循環週期,這就是爲什麼他們仍然在同一時間出現。如果你想要一個一個的效果,我推薦使用動畫。 – Joe

+0

這就是我所認爲的(大量視圖排隊進入相同的運行循環週期)。如何使用動畫工作? 'addSubview:'不是「可動畫的」... – pgb

0

值得指出的另一件事是,你已經創建了一個串行隊列(bandview)派遣的UIView創建請求進入,但是這也意味着每個創建請求將線性順序發生VS最並行的方式可能被創建。如果這不是所需的行爲,您可以嘗試將創建請求分派到全局併發隊列之一。

+0

這是故意的,因爲我需要累積每個視圖的寬度,所以我不能並行執行。 – pgb