[SWIFT] Implementieren Sie iOS14 UICollectionView mit CustomCell.

Einführung

Das letzte Mal habe ich [Artikel zur Implementierung von UICollectionView von iOS14] geschrieben (https://qiita.com/maruiyugo/items/70b02bf22bec51f3b97a "Qiita"). Es scheint also, dass sich der Umgang mit benutzerdefinierten Zellen geändert hat. Schreiben wir dies also auch in den Artikel! Ich habe es in dem Gedanken geschrieben, aber es war schwierig, weil sich die Behandlung gegenüber zuvor erheblich geändert hat. Ich mache mir Sorgen, wenn es richtig ist, also irre ich mich hier, du solltest das schreiben! Bitte kommentieren Sie, wenn Sie welche haben: durchhalten:

Einführungsecke für benutzerdefinierte Zellenzeichen

UICollectionViewListCell-Klasse

Es ist nur eine Zellklasse. Ich mache nichts Besonderes.

UICellConfigurationState-Klasse

Es hält den Staat. "isSelected" und "isFocused" werden standardmäßig bereitgestellt. Sie können auch anpassen und hinzufügen. (Diesmal nicht behandelt.)

UIView-Klasse

Erstellen Sie eine benutzerdefinierte Ansicht.

UIContentConfiguration-Klasse

Eine Klasse, die eine benutzerdefinierte Ansicht initialisiert, die anzuzeigenden Daten von der Zelle und "UICellConfigurationState" empfängt, sie in der benutzerdefinierten Ansicht widerspiegelt und die Ansicht an die Zelle zurückgibt. Es ist das Wichtigste. Es ist Nummer 4.

Implementierungsimage

Setzen Sie einen Stern, um einen Unterschied zum vorherigen Artikel zu machen. ..

Alle Codes

Insgesamt gibt es 6 Dateien. 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
            
            //Für den Abschnittstitel wird eine normale Zelle verwendet.
            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)
    }
}

Kaisetsu

Dies ist der einzige Ort, der etwas Besonderes ist. Beim Festlegen von "UICollectionViewListCell" habe ich die Methode "defaultContentConfiguration" aufgerufen, um den Inhalt festzulegen. Da der Prozess jedoch auf "SimpleCustomCell" verschoben wurde, übergebe ich hier nur "title".

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
    }
}

Kaisetsu

updateConfiguration ist eine Methode, die aufgerufen wird, wenn die Daten auf die collectionView angewendet werden und wenn die Methode setNeedsUpdateConfiguration aufgerufen wird und das Layout aktualisiert werden muss. Hier wird die Konfiguration initialisiert und die Daten (Titel) werden gepackt und in die contentConfiguration der Zelle selbst gesetzt. (Der Argumentstatus wird nicht verwendet, da er diesmal den Status nicht verarbeitet.)

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
    }
}

Kaisetsu

Die Methode makeContentView ist eine Methode, die eine Ansicht erstellt, die in einer Zelle angezeigt werden soll. Sich als Argument an die Ansicht übergeben. Die "aktualisierte" Methode ist eine Methode, die aufgerufen wird, wenn sich der Status ändert. Es wird nicht verwendet.

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
    }
}

Kaisetsu

Ich lade xib und setze die übergebenen Konfigurationsdaten auf Label. Insbesondere gibt es nichts zu erklären.

Zusammenfassung

Es scheint, dass die Verwendung von "Konfiguration" die Wiederverwendung leichter und einfacher macht. Im Vergleich zur herkömmlichen Methode mit Delegate und DataSource wusste ich nicht, wo und welche Methode aufgerufen wurde, und ich hatte das Gefühl, dass das Gefühl der Black Box zunahm. Wird es mich nicht stören, wenn ich mich daran gewöhnt habe? ..

Als nächstes werde ich einen Artikel mit dem Status schreiben, den ich dieses Mal nicht verwendet habe. Bitte LGTM, wenn Sie möchten, da es kahl sein wird \ (^ o ^) /

Klicken Sie hier für Git! https://github.com/ymarui/iOS14_UICollectionView_sample

Verweise

https://qiita.com/shiz/items/4227accc7d13ae439d1d#推奨される使用方法 https://swiftsenpai.com/development/collectionview-expandable-list-part2/

Recommended Posts

Implementieren Sie iOS14 UICollectionView mit CustomCell.
Implementieren Sie iOS14 UICollectionView mit dem minimal erforderlichen Code.
Warum mit Singleton anstelle einer statischen Methode implementieren?
Implementieren Sie GraphQL mit Spring Boot
Implementierung von XLPagerTabStrip mit TabBarController
jCaptcha-Reload mit Ajax implementiert