将UICollectionLayoutListConfiguration与情节提要一起使用

时间:2020-10-23 14:38:00

标签: ios swift uicollectionview uikit

您可以在iOS 14中将新的UICollectionLayoutListConfiguration API与情节提要中的收藏夹视图一起使用吗?

我在情节提要中有一个UICollectionViewController,我使用以下自定义列表布局对其进行配置:

var config = UICollectionLayoutListConfiguration(appearance: .plain)
let layout = UICollectionViewCompositionalLayout.list(using: config)
collectionView.setCollectionViewLayout(layout, animated: false)
collectionView.dataSource = dataSource

(在情节提要中,只能使用流或自定义布局来设置视图)

这使用标准的可扩散数据源:

return UICollectionViewDiffableDataSource(collectionView: collectionView) { (collectionView, indexPath, item) in
    guard let cell = collectionView.dequeueReusableCell(
        withReuseIdentifier: "SomeCell",
        for: indexPath
    ) as? SomeCell else {
        fatalError("Couldn't dequeue cell \(reuseIdentifier)")
    }

    cell.setItem(item)
    return cell
}

尽管我在旋转屏幕之前一切正常,但是我得到了一些非常奇怪的行为,例如IBOutlets在旋转屏幕时为零。

我没有找到调试这里发生的事情的好方法,堆栈跟踪看起来正确,并且单元的类已初始化并且在主线程上运行。

Strange nil IBOutlot

2 个答案:

答案 0 :(得分:1)

我已经复制了代码的每一步,最终结果符合我的预期。

enter image description here

这是肖像模式下的最终结果

enter image description here

这是横向模式的最终结果

我打算做的是在集合视图中显示数字列表,以下是必要的文件供您参考:

The UICollectionViewController

import UIKit

private let reuseIdentifier = "SomeCell"

enum Section {
  case main
}

class SampleCollectionViewController: UICollectionViewController {
  
  var dataSource: UICollectionViewDiffableDataSource<Section, Int>!
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    self.collectionView.setCollectionViewLayout(getLayout(), animated: false)
    configureDataSource()
  }
  
  func getLayout() -> UICollectionViewCompositionalLayout {
    
    let config = UICollectionLayoutListConfiguration(appearance: .plain)
    let layout = UICollectionViewCompositionalLayout.list(using: config)
    return layout
  }
  
  func configureDataSource() {
    
    dataSource = UICollectionViewDiffableDataSource<Section, Int>(collectionView: self.collectionView, cellProvider: { (collectionView, indexPath, number) -> UICollectionViewListCell? in
      
      guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as? SomeCell else {
        fatalError("Cannot create cell")
      }
      
      cell.label.text = number.description
      return cell
    })
    
    var initialSnapshot = NSDiffableDataSourceSnapshot<Section, Int>()
    initialSnapshot.appendSections([.main])
    initialSnapshot.appendItems(Array(1...100), toSection: .main)
    
    dataSource.apply(initialSnapshot, animatingDifferences: false)
  }
}

The UICollectionViewListCell

import UIKit

class SomeCell: UICollectionViewListCell {
    
  @IBOutlet weak var label: UILabel!
  
  override func updateConstraints() {
    super.updateConstraints()
    
    label.textColor = .blue
  }
}

情节提要设置: enter image description here enter image description here enter image description here

我按照以下标准步骤进行了所有这些操作,

重要说明::我发现您的实现方式与众不同的一个潜在地方是您拥有dequeued 一个单元格 withReuseIdentifier 为< / strong> "SomeCell",但是您显示的引发错误的单元格类别为TextCell,如果您可以提供更多有关其的详细信息,则有助于缩小所面临的错误。

答案 1 :(得分:0)

这是简化的演示。大部分基于某种方式来复制您的代码。

通过Xcode 12 / iOS 14测试

demo

struct SomeItem: Hashable {
    let id = UUID()
    var value: String
}

class SomeCell: UICollectionViewCell {
    @IBOutlet weak var label: UILabel!
    var item: SomeItem!
    
    func setItem(_ item: SomeItem) {
        self.item = item
        label.text = item.value
    }
    
    override func awakeFromNib() { // called when all outlets connected
        super.awakeFromNib()
        label.textColor = .blue
    }
}

class ViewController: UICollectionViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let config = UICollectionLayoutListConfiguration(appearance: .plain)
        let layout = UICollectionViewCompositionalLayout.list(using: config)
        collectionView.setCollectionViewLayout(layout, animated: false)
        collectionView.dataSource = dataSource
    }

    lazy var dataSource = {
        UICollectionViewDiffableDataSource<Int, SomeItem>(collectionView: self.collectionView) { (collectionView, indexPath, item) in
             guard let cell = collectionView.dequeueReusableCell(
                  withReuseIdentifier: "SomeCell",
                  for: indexPath
             ) as? SomeCell else {
                  fatalError("Couldn't dequeue cell")
             }

             cell.setItem(item)
             return cell
        }
    }()
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        var snapshot = NSDiffableDataSourceSnapshot<Int, SomeItem>()
        snapshot.appendSections([0])
        snapshot.appendItems([SomeItem(value: "Jan"), SomeItem(value: "Fab"), SomeItem(value: "Mar")])
        dataSource.apply(snapshot)
    }
}

情节提要中没有什么特别的-仅对视图控制器和单元格应用了自定义类(为方便起见,标签居中)并进行了自定义集合视图布局:

demo2

demo3

demo4