iOS開發-beginUpdates && endUpdates用法

來源:互聯網
上載者:User

標籤:

本篇主要介紹使用beginUpdates和endUpdates方法對UITableView的Cell進行大量操作更新。首先給出過程中依賴的資料來源:

    self.arraySections = [NSMutableArray arrayWithCapacity:0];    NSMutableArray *array1 = [NSMutableArray arrayWithObjects:@"Apple",@"Alice",@"Apache",@"amount",@"application",@"abort",@"action",@"alert", nil];    NSMutableArray *array2 = [NSMutableArray arrayWithObjects:@"BMW",@"Beach",@"Boom",@"Band",@"BBBB",@"baby",@"bear", nil];    NSMutableArray *array3 = [NSMutableArray arrayWithObjects:@"Cache",@"Clean",@"clear",@"Class",@"Client",@"count",@"ccc",@"can",@"ccccca",@"c1618", nil];    [self.arraySections addObject:array1];    [self.arraySections addObject:array2];    [self.arraySections addObject:array3];

beginUpdatesendUpdates方法是一對綁定在一起的方法,用來對UITableView批次更新操作。先看一下多個插入刪除操作不使用beginUpdatesendUpdates的情況:

    NSMutableArray *array1 = (NSMutableArray *)self.arraySections[0];    //操作1 刪除    [array1 removeObjectAtIndex:0];    [self.tableMain deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];    //操作2 插入    [array1 insertObject:@"insert" atIndex:3];    [self.tableMain insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:3 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];    //操作...

這種做法對於每一個操作,是嚴格按照順序執行的,先執行操作1,再執行操作2…再執行任意一個操作的時候,先更新資料來源,然後調用表視圖的相關操作,該操作方法執行完畢後,會立即調用相關的代理方法更新表視圖。更新完畢後繼續執行下一個操作…即整個過程是不斷地調用代理方法來更新表視圖。因此對於這種按序更新的方法,每一個更新操作並不是同時進行的,如果有很多個操作,可能通過肉眼就能看出更新的先後,這通常並不是我們想要的。

通過beginUpdatesendUpdates則可以批量處理操作,區別於上面的操作一個一個執行然後不斷更新表視圖,批量處理實現了在所有操作執行完後調用代理方法一次性更新表視圖,這種方法保證了所有操作最終是同時更新的。

beginUpdatesendUpdates批次更新有三部曲:

  1. 更新資料來源(所有操作)
  2. 建立相應的indexPaths數組
  3. 執行操作

下面舉例說明:

    NSMutableArray *array1 = (NSMutableArray *)self.arraySections[0];    [array1 removeObjectAtIndex:0];    [array1 removeObjectAtIndex:2];    [array1 insertObject:@"111" atIndex:1];    [array1 insertObject:@"333" atIndex:3];    //建立相應的indexPaths數組    NSArray *indexPathsDelete = @[[NSIndexPath indexPathForRow:0 inSection:0],[NSIndexPath indexPathForRow:2 inSection:0]];    NSArray *indexPathsInsert = @[[NSIndexPath indexPathForRow:1 inSection:0],[NSIndexPath indexPathForRow:3 inSection:0]];    //執行操作    [self.tableMain beginUpdates];    [self.tableMain deleteRowsAtIndexPaths:indexPathsDelete withRowAnimation:UITableViewRowAnimationFade];    [self.tableMain insertRowsAtIndexPaths:indexPathsInsert withRowAnimation:UITableViewRowAnimationFade];    [self.tableMain endUpdates];

beginUpdates和endUpdates方法對之間的操作執行後並沒有立刻更新表視圖,而是等endUpdates方法返回後才調用代理方法一次性更新的,因此所有更新動畫都是同時執行的。

執行前後的表視圖顯示如下:

執行前:

執行後:

執行完這段代碼,產生如下幾個問題:

  • 問題一:代理方法是根據資料來源來更新視圖的,既然資料來源已經更新了,endUpdates返回後代理方法也會執行,那麼beginUpdatesendUpdates之間的操作有什麼用呢?

    猜想這個過程並不是這麼簡單的,假如真的只是根據資料來源的更新來重新整理視圖的話,我更新資料來源一個reloadData不就搞定了,還要那麼麻煩幹嘛!怎麼驗證這個猜想?很簡單,把資料來源更新後的結果列印出來看看,如果和表視圖顯示的不一致,那麼猜想就是合理的。列印結果如下:

    事實上對比發現,兩者確實是不一致的;另外還有一種驗證方法,把beginUpdates和endUpdates之間的更新操作全都注釋掉,再次運行就發現表視圖根本就不更新了,斷點發現cellForRowAtIndexPath:根本就沒被調用。種種跡象表明,insert/delete這些更新方法定有什麼不可告人的秘密!具體這個秘密是什嗎?是怎麼和資料來源配合的?我也不得而知!

  • 問題二:beginUpdatesendUpdates之間的insert操作和delete操作交換順序會影響結果嗎?

    答案是不會!交換了兩個操作方法,執行結果無差。官方文檔中找到了這樣的說明:
    The code calls the deleteRowsAtIndexPaths:withRowAnimation: method after it calls insertRowsAtIndexPaths:withRowAnimation:. However, this is not the order in which UITableView completes the operations. It defers any insertions of rows or sections until after it has handled the deletions of rows or sections.
    大致意思就是:deletion操作比insertion操作有更高執行優先權。
    因此在執行insertion操作的時候,deletion操作已經執行完畢。這樣就要小心了,因為deletion是在原始表視圖的indexPaths上操作的,而insertion則是在deletion操作之後的表視圖的indexPaths上操作的,兩者參照不同!官方文檔中也給了這樣的提示:
    Deletion and reloading operations within an animation block specify which rows and sections in the original table should be removed or reloaded; insertions specify which rows and sections should be added to the resulting table.
    端倪在於這個original tableresulting table

  • 問題三:資料來源更新順序對結果有影響嗎?

    答案是有!將上面代碼中將資料來源插入代碼放到刪除前面,運行結果變了,而且變成一種我看了變天也沒看出規律的結果。


    因此再一次證明了問題一種的結論,更新操作函數和資料來源真的很有一腿!好了說正經的,如果誰知道操作函數和資料來源之間的關聯,麻煩告知小弟,非常感謝!!雖然資料來源”插入”在”刪除”前的結果沒有預料到,但是”刪除”在”插入”之前的結果還是在意料之中的,因此以後預設就把”刪除”寫在”插入”前面吧,實屬無奈!

下面再看一個例子,用來證明問題二中的相關結論。

//更新資料來源    NSMutableArray *array1 = (NSMutableArray *)self.arraySections[0];    NSMutableArray *array3 = (NSMutableArray *)self.arraySections[2];    [array1 removeObjectAtIndex:0];             //刪除第0分組第0記錄    [array1 removeObjectAtIndex:2];             //刪除第0分組第2記錄    [self.arraySections removeObjectAtIndex:1]; //刪除第1分組    [array1 insertObject:@"1111" atIndex:1];    //插入第0分組第1記錄    [array3 insertObject:@"3333" atIndex:0];    //插入第2分組第0記錄    //建立相應的indexPaths數組    NSArray *indexpathsDelete = @[[NSIndexPath indexPathForRow:0 inSection:0],[NSIndexPath indexPathForRow:2 inSection:0]];    NSArray *indexpathsInsert = @[[NSIndexPath indexPathForRow:1 inSection:0],[NSIndexPath indexPathForRow:0 inSection:1]/*要插入的是第2分組第0記錄,但這裡的分組數卻為1,思考原因*/];    //執行操作    [self.tableMain beginUpdates];    [self.tableMain insertRowsAtIndexPaths:indexpathsInsert withRowAnimation:UITableViewRowAnimationFade];    [self.tableMain deleteSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationFade];    [self.tableMain deleteRowsAtIndexPaths:indexpathsDelete withRowAnimation:UITableViewRowAnimationFade];    [self.tableMain endUpdates];

執行後介面如下:

由於在執行insert之前,delete已經執行完畢了,原始的第1分組已經被刪除了,原始第2分組變為第1分組,因此insert方法所要插入的第二個cell的indexPath對應的section為1而不是2。

總結一下:如果只是單純的一個插入或者刪除操作,沒必要用beginUpdatesendUpdates包裹操作方法;若是大量操作,建議用endUpdatesendUpdates,已保證介面對各個更新操作同時響應。

iOS開發-beginUpdates && endUpdates用法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.