Last time, I wrote Article implementing UICollectionView of iOS14, so it seems that the handling of custom cells has changed, so let's write this in the article as well! I wrote it thinking that, but it was difficult because the treatment has changed considerably from before. I'm worried if it's right, so I'm wrong here, you should write this! Please comment if you have any: persevere:
It's just a cell class. I don't do anything in particular.
It keeps the state.
ʻIsSelected and ʻisFocused
are provided by default.
You can also customize and add.
(Not dealt with this time.)
Create a custom view.
A class that initializes a custom view, receives the data to be displayed from the cell and ʻUICellConfigurationState`, reflects it in the custom view, and returns the view to the cell. It is the most important. It is number 4.
Exquisitely put a star to make a difference from the previous article. ..
There are 6 files in total.
SimpleCustomCell.storyboard
SimpleCustomCellViewController.swift
SimpleCustomCell.swift
SimpleCustomCellConfiguration.swift
SimpleCustomCellView.xib
SimpleCustomCellView.swift
SimpleCustomCellViewController.swift
SimpleCustomCellViewController.swift
class SimpleCustomCellViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
enum Section: CaseIterable {
case kanto
case kyusyu
}
let data: [Section: [String]] = [
.kanto: ["Kanto", "Tokyo", "Chiba"],
.kyusyu: ["Kyusyu", "Fukuoka", "Miyazaki"]
]
var collectionViewDataSource: UICollectionViewDiffableDataSource<Section, String>!
override func viewDidLoad() {
super.viewDidLoad()
var layoutConfig = UICollectionLayoutListConfiguration(appearance: .grouped)
layoutConfig.headerMode = UICollectionLayoutListConfiguration.HeaderMode.firstItemInSection
let layout = UICollectionViewCompositionalLayout.list(using: layoutConfig)
collectionView.collectionViewLayout = layout
collectionViewDataSource = createDataSource()
reloadList()
}
func createDataSource() -> UICollectionViewDiffableDataSource<Section, String> {
let normalCell = UICollectionView.CellRegistration<UICollectionViewListCell, String> { (cell, indexPath, text) in
var content = cell.defaultContentConfiguration()
content.text = text
cell.contentConfiguration = content
}
let customCell = UICollectionView.CellRegistration<SimpleCustomCell, String> { (cell, indexPath, text) in
cell.title = text
}
return UICollectionViewDiffableDataSource<Section, String>(collectionView: collectionView) {
(collectionView, indexPath, text) -> UICollectionViewCell? in
//A normal cell is used for the section title.
if indexPath.row == 0 {
return collectionView.dequeueConfiguredReusableCell(using: normalCell, for: indexPath, item: text)
} else {
return collectionView.dequeueConfiguredReusableCell(using: customCell, for: indexPath, item: text)
}
}
}
func reloadList(){
var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
snapshot.appendSections(Section.allCases)
snapshot.appendItems(data[.kanto]!, toSection: .kanto)
snapshot.appendItems(data[.kyusyu]!, toSection: .kyusyu)
collectionViewDataSource.apply(snapshot)
}
}
This is the only place that is special.
ʻWhen setting UICollectionViewListCell, I called the
defaultContentConfiguration method to set content, but since the process has moved to
SimpleCustomCell, I only pass
title` here.
let customCell = UICollectionView.CellRegistration<SimpleCustomCell, String> { (cell, indexPath, text) in
cell.title = text
}
SimpleCustomCell.swift
SimpleCustomCell.swift
class SimpleCustomCell: UICollectionViewListCell {
var title: String!
override func updateConfiguration(using state: UICellConfigurationState) {
var newConfiguration = SimpleCustomCellConfiguration()
newConfiguration.title = title
contentConfiguration = newConfiguration
}
}
ʻUpdateConfiguration is a method that is called when data is ʻapply
to the collectionView and when the setNeedsUpdateConfiguration
method is called and the layout needs to be updated.
Here, the Configuration is initialized, and the data (title) is packed and set to the contentConfiguration of the cell itself.
(The argument state is unused because it does not handle the state this time.)
SimpleCustomCellConfiguration.swift
SimpleCustomCellConfiguration.swift
struct SimpleCustomCellConfiguration: UIContentConfiguration, Hashable {
var title: String?
func makeContentView() -> UIView & UIContentView {
return SimpleCustomCellView(configuration: self)
}
func updated(for state: UIConfigurationState) -> Self {
return self
}
}
The makeContentView
method is a method that creates a view to display in a cell.
Passing itself to the view as an argument.
The ʻupdated` method is a method that is called when the state changes. It is unused.
SimpleCustomCellView.xib(.swift)
SimpleCustomCellView.swift
class SimpleCustomCellView: UIView, UIContentView {
@IBOutlet var nameLabel: UILabel!
var configuration: UIContentConfiguration
init(configuration: SimpleCustomCellConfiguration) {
self.configuration = configuration
super.init(frame: .zero)
loadNib()
setUpUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func loadNib() {
let nib = UINib(nibName: "\(SimpleCustomCellView.self)", bundle: nil)
guard let view = nib.instantiate(withOwner: self, options: nil).first as? UIView else { return }
view.frame = frame
addSubview(view)
}
private func setUpUI() {
guard let configuration = configuration as? SimpleCustomCellConfiguration else { return }
nameLabel.text = configuration.title
}
}
I'm loading xib and setting the data of the passed configuration to Label. There is nothing to explain in particular.
It seems that using Configuration
makes it lighter and easier to reuse.
Compared to the conventional methods using Delegate and DataSource, I didn't know where and which method was called, and I felt that the feeling of a black box increased.
Will it not bother me once I get used to it? ..
Next, I will write an article using the state that I did not use this time. Please LGTM if you like because it will be bald \ (^ o ^) /
Click here for git! https://github.com/ymarui/iOS14_UICollectionView_sample
https://qiita.com/shiz/items/4227accc7d13ae439d1d#推奨される使用方法 https://swiftsenpai.com/development/collectionview-expandable-list-part2/
Recommended Posts