iOS 14 UICollectionView 新功能 讓我們跟 Cell Item Identifier 說再見!


本篇原文(標題:What’s New in iOS 14’s UICollectionView?)刊登於作者的 Medium,由 Anupam Chugh 所著,並授權翻譯及轉載。

雖然在 WWDC 2020 沒有介紹 SwiftUI 引入 Collection View 的消息,但這無阻 UICollectionView 新增強大的新功能。

iOS 13 時,在 CollectionViews 中引進 CompositionalLayoutsDiffableDataSources,為 UICollectionView 的建構 Layout 以及 DataSources 帶來更多的彈性。

到了 iOS 14,CollectionView API 添加了三個新的 API,分別負責 Layout、DataSources、及 Cell,也就是構建 Collection View 的三個要素:

  • Lists 新增於 CompositionalLayouts 裡,為 CollectionViews 帶來類似 UITableView 的樣式。
  • UICollectionView.CellRegistration 讓你以完全不同的方式使用新 Configuration API 來配置 Cell。另外,還有一個新的 UICollectionViewListCell 具體類別 (concrete class),在預設情況下為 cell 提供類似列表的內容樣式。
  • Diffable Data Source 包含了 Section Snapshots,允許以 Section 為基礎更新更多資料。這對於建立 Outlined Styled 這個 iOS 14 的新層次列表非常有用。

在下一個段落中,我們將探討前兩個新增的 API。來看看如何用 iOS 14 的新方法,在 UICollectionView 中構建 Layout 和 Cell 吧!

iOS 14 Cell 的配置與註冊

iOS 14 引進了全新的 Cell Configuration API,來配置我們的 CollectionView Cell 和 TableView Cell。

也就是說,我們不需要像以前一樣,直接在 UITableViewCellUICollectionViewCell 上設定屬性。

新的 Configuration API 讓我們能夠使用一個內容配置,來設定 Cell 的內容與樣式,或是依據不同的狀態作更新:

let cellRegistration = UICollectionView.CellRegistration<UICollectionViewCell, String> { cell, indexPath, name in

            var content = UIListContentConfiguration.cell()
            content.text = name
            cell.contentConfiguration = content
}

UICollectionViews 裡,我們有新的 UICollectionViewListCell。我們可以用以下方式,直接擷取它的預設配置:

var content = listCell.defaultContentConfiguration()

這樣一來,我們就能夠避免使用 Cell Identifiers、及過去我們寫來確保 Cell 有註冊的 if letguard let 陳述句。

更重要的是,我們不再直接地存取 Cell 的 Label 與 Image 屬性,這使我們能夠建構出讓 TableViewCollectionView 與自定義 Cell 都可以使用的配置。

除了 contentConfiguration 以外,我們也可以利用 backgroundConfiguration 來設定背景屬性,另外還有 leadingSwipeActionsConfigurationtrailingSwipeActionsConfiguration 讓我們能輕鬆地把類似 UITableView 的滑動行為,直接嵌入到 UICollectionView Cell 實作。

我們剛剛建立的新 UICollectionView.CellRegistration 結構,在傳送到 dequeueConfiguredReusableCell 內部時會自動處理 Cell 的註冊,因此你不再需要使用 Identifiers 來註冊 Cell。

iOS 14 CollectionViews 的新列表 Layouts

上個段落我們提到 UICollectionViewListCell,想必你也猜到我們在 Compositional Layouts 上有個新的列表 Layout。

要快速設定這個 Layout,我們只需要傳入 UICollectionViewListConfiguration。除了以下的 Plain 樣式外,我們還可以把樣式設定為 groupedinsetGroupedsideBar、以及 sideBarPlain

let config = UICollectionLayoutListConfiguration(appearance: .plain)
let layout = UICollectionViewCompositionalLayout.list(using: config)

新的 Lists 支援 UICollectionView 的好處,是為我們提供了自適應 (self-sizing) Cell 的開箱即用 (out-of-the-box) 支援。

我們還可以按 Section 來建立列表,方法是傳入 Compositional Layout 裡的 NSCollectionSectionLayout.list

要在 UICollectionView 裡自定義列表的 headerfooter,就與我們在 UITableView 的做法有點不同。

你需要在列表的配置中,以下列方式調用 headerModefooterMode

config.headerMode = .supplementary
config.footerMode = .supplementary

接著,你需要調用 Diffable Data Source 上的 supplementaryViewProvider,來提供視圖。在其中,你可以設定 dequeueConfiguredReusableSupplementary 函數,並將它傳送至 Header 配置。

現在,讓我們整合上述的新功能(Cell Configuration API、List Layout 與 Registrations)。

我們已經在 UIViewController 中設定好簡單的 UICollectionView,如下所述:

class ViewController: UIViewController {

    var items = Array(0...100).map { String($0) }
    var collectionView : UICollectionView!
    private lazy var dataSource = makeDataSource()

    override func viewDidLoad() {
        super.viewDidLoad()

        let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
        let layout = UICollectionViewCompositionalLayout.list(using: config)

        collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        self.view.addSubview(collectionView)
        //add autolayout constraints

        collectionView.dataSource = dataSource

        var snapshot = NSDiffableDataSourceSnapshot<String,String>()
        snapshot.appendSections(["Section 1"])
        snapshot.appendItems(items)
        dataSource.apply(snapshot, animatingDifferences: true)

    }


    func makeDataSource() -> UICollectionViewDiffableDataSource<String, String> {

        let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { cell, indexPath, name in

            var content = cell.defaultContentConfiguration()
            content.text = name
            cell.contentConfiguration = content
        }

        return UICollectionViewDiffableDataSource<String, String>(
                    collectionView: collectionView,
                    cellProvider: { collectionView, indexPath, item in
                        collectionView.dequeueConfiguredReusableCell(
                            using: cellRegistration,
                            for: indexPath,
                            item: item
                        )
                    }
                )
    }
}

在模擬器上執行 App,你會看到以下的結果:

An iPhone screenshot that shows a UITableView like list inside UICollectionView in iOS 14

總結

我們來總結一下:

  • iOS 14 引進了新的 CellRegistration 技術,不再需要使用 Cell Identifiers 來註冊 Cell。
  • 新的 Configuration API 封裝了 Cell 的內容及背景視圖屬性。UICollectionViewListCell 提供了一個預設配置,我們可以表情況作設定及更新。
  • 在設定 Cell 配置的時候,我們可以直接做客製化設定,像是滑動動作、設定 Accessories 等,讓我們維持單一的 source。
  • UICollectionView 的新列表看起來像 UITableView,我們可以使用適當的 Header 及 Footer 指定 Layout 和配置(甚至可以 Section 為基礎),來輕鬆組成列表。

我們很快地將所學內容整合起來,以宣告式建構了一個簡單的 UICollectionView。是時候向 Cell Item Identifier 說再見了!

在下篇文章中,我們將關注 iOS 14 的 Diffable Data Sources 有什麼新功能,請密切留意。本篇文章到此為止,謝謝你的閱讀。

特別鳴謝 Zack Shapiro。

本篇原文(標題:What’s New in iOS 14’s UICollectionView?)刊登於作者的 Medium,由 Anupam Chugh 所著,並授權翻譯及轉載。

作者簡介:Anupam Chugh,深入探索 ML 及 AR 的 iOS Developer。喜愛撰寫關於想法、科技、與程式碼的文章。歡迎到我的 Blog 閱讀更多文章,或在 LinkedIn 上關注我。

譯者簡介:楊敦凱-目前於科技公司擔任 iOS Developer,工作之餘開發自有 iOS App 同時關注網路上有趣的新玩意、話題及科技資訊。平時的興趣則是與自身專業無關的歷史、地理、棒球。來信請寄到:[email protected]


此文章為客座或轉載文章,由作者授權刊登,AppCoda編輯團隊編輯。有關文章詳情,請參考文首或文末的簡介。

blog comments powered by Disqus
Shares
Share This