Hi everybody.
I decided to make two UICollectionView offices on one screen.
SectionHeade registered for the second one.
I constantly get an error that the header is not registered.
Вопрос такой не могу лия как нибудь игнорировать первый UICollectionView "collectionDevices"? Turn him off header?
Thread 1: "could not dequeue a view of kind: UICollectionElementKindSectionHeader with identifier headerCellForModel - must register a nib or a class for the identifier or connect a prototype cell in a storyboard"
func collectionView(
_ collectionView: UICollectionView,
viewForSupplementaryElementOfKind kind: String,
at indexPath: IndexPath
) -> UICollectionReusableView {
if collectionView == self.collectionModels {
switch kind {
case UICollectionView.elementKindSectionHeader:
let seriesTitle = getSeriesName(section: indexPath.section)
let header = UICollectionReusableView()
if let headerCell = collectionView.dequeueReusableSupplementaryView(
ofKind: kind,
withReuseIdentifier: collectionViewHeaderFooterReuseIdentifier,
for: indexPath
) as? SectionHeaderForModelCell {
headerCell.labelTitle.text = seriesTitle
return headerCell
}
return header
default:
return UICollectionViewCell()
}
}
}
//
// MainRepairViewController.swift
// Apple №1
//
// Created by Steven Kirke on 16.01.2024.
//
import UIKit
protocol ICustomCellForModelDelegate: AnyObject {
func viewTapped(text: String)
}
protocol IMainRepairViewLogic: AnyObject {
/// Отображение получаемых из вне данных.
/// - Parameters:
/// - contactList: Модель контактов, для отображения во View.
func render(viewModel: [MainRepairModel.ViewModel.Device])
}
final class MainRepairViewController: UIViewController {
// MARK: - Dependencies
var iterator: IMainRepairIterator?
// MARK: - Private properties
private let customUI = CustomUI()
private var headerForCellModel = SectionHeaderForModelCell()
private let collectionViewHeaderFooterReuseIdentifier = "headerCellForModel"
private lazy var collectionDevices = customUI.createCollectionView(direction: .horizontal)
private lazy var collectionModels = customUI.createCollectionView(direction: .vertical)
private var modelForDisplayDevices: [Device] = []
private var modelForDisplaySeries: [Series] = []
private var currentDevice: Int = 0
// MARK: - Initializator
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
// MARK: - Public methods
override func viewDidLoad() {
super.viewDidLoad()
setupConfiguration()
addUIView()
iterator?.fetchCatalog()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
setupLayout()
}
}
// - MARK: Handler for models
private extension MainRepairViewController {
/**
Получение количества девайсов.
- Returns: Количество девайсов.
*/
func getDevicesCount() -> Int {
!modelForDisplayDevices.isEmpty ? modelForDisplayDevices.count : 0
}
/**
Получение количество серий для текущего девайся.
- Parameters:
- index: Int Число, индекс текущего элемента массива.
- Returns: Количество серий.
*/
func getSeriesCount(indexDevice: Int) -> Int {
if getDevicesCount() > 0 {
if indexDevice < modelForDisplayDevices[indexDevice].series.count {
return modelForDisplayDevices[indexDevice].series.count
}
}
return 0
}
/**
Название серии..
- Parameters:
- section: Int Текущая секция.
- Returns: Название серии устройств.
*/
func getSeriesName(section: Int) -> String {
if getSeriesCount(indexDevice: currentDevice) > 0 {
if section < modelForDisplayDevices[currentDevice].series.count {
return modelForDisplayDevices[currentDevice].series[section].titleSeries
}
}
return "Empty"
}
func getModelsCount(section: Int) -> Int {
if getDevicesCount() > 0 && getSeriesCount(indexDevice: currentDevice) > 0 {
if modelForDisplayDevices[currentDevice].series[section].models.count > 0 {
let count = modelForDisplayDevices[currentDevice].series[section].models.count
return count
}
}
return 0
}
func getModelsTitle(section: Int, indexPath: Int) -> String {
if getDevicesCount() > 0 && getSeriesCount(indexDevice: currentDevice) > 0 {
if modelForDisplayDevices[currentDevice].series[section].models.count > 0 {
if indexPath < modelForDisplayDevices[currentDevice].series[section].models.count {
let title = modelForDisplayDevices[currentDevice].series[section].models[indexPath].title
return title
}
}
}
return "Empty"
}
}
// - MARK: Add UIView in Controler
private extension MainRepairViewController {
/// Добавление элементов UIView в Controller.
func addUIView() {
let views: [UIView] = [collectionDevices, collectionModels]
views.forEach(view.addSubview)
}
}
// - MARK: Initialisation configuration
private extension MainRepairViewController {
/// Настройка UI элементов
func setupConfiguration() {
view.backgroundColor = Theme.backgroundColor
collectionDevices.backgroundColor = Theme.backgroundColor
collectionDevices.showsHorizontalScrollIndicator = false
collectionDevices.register(CustomCellForDevice.self, forCellWithReuseIdentifier: "cell")
collectionDevices.delegate = self
collectionDevices.dataSource = self
collectionModels.backgroundColor = Theme.backgroundColor
collectionModels.register(
SectionHeaderForModelCell.self,
forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
withReuseIdentifier: collectionViewHeaderFooterReuseIdentifier
)
collectionModels.register(CustomCellForModel.self, forCellWithReuseIdentifier: "cell")
collectionModels.showsVerticalScrollIndicator = false
collectionModels.delegate = self
collectionModels.dataSource = self
}
}
// - MARK: Initialisation constraint elements.
private extension MainRepairViewController {
/// Верстка элементов UI.
/// - Note: Добавление constraints для UIView элементов.
func setupLayout() {
NSLayoutConstraint.activate([
collectionDevices.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
collectionDevices.leadingAnchor.constraint(equalTo: view.leadingAnchor),
collectionDevices.trailingAnchor.constraint(equalTo: view.trailingAnchor),
collectionDevices.heightAnchor.constraint(equalToConstant: 100),
collectionModels.topAnchor.constraint(equalTo: collectionDevices.bottomAnchor, constant: 0),
collectionModels.leadingAnchor.constraint(equalTo: view.leadingAnchor),
collectionModels.trailingAnchor.constraint(equalTo: view.trailingAnchor),
collectionModels.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
}
extension MainRepairViewController:
UICollectionViewDelegateFlowLayout,
UICollectionViewDataSource,
UICollectionViewDelegate {
/// Количество секции в текущем UICollectionView.
func numberOfSections(in collectionView: UICollectionView) -> Int {
switch collectionView {
case self.collectionDevices:
return getDevicesCount()
case self.collectionModels:
return getSeriesCount(indexDevice: currentDevice)
default:
return 0
}
}
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath
) -> CGSize {
switch collectionView {
case self.collectionDevices:
return CGSize(width: 120, height: 40)
case self.collectionModels:
return CGSize(width: collectionView.frame.size.width, height: 40)
default:
return CGSize(width: 0, height: 0)
}
}
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
referenceSizeForHeaderInSection section: Int
) -> CGSize {
switch collectionView {
case self.collectionDevices:
return CGSize(width: 10, height: 0)
case self.collectionModels:
return CGSize(width: collectionView.frame.size.width, height: 40)
default:
return CGSize(width: 0, height: 0)
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
switch collectionView {
case self.collectionDevices:
return 1
case self.collectionModels:
return getModelsCount(section: section)
default:
return 0
}
}
func collectionView(
_ collectionView: UICollectionView,
viewForSupplementaryElementOfKind kind: String,
at indexPath: IndexPath
) -> UICollectionReusableView {
if collectionView == self.collectionModels {
switch kind {
case UICollectionView.elementKindSectionHeader:
let seriesTitle = getSeriesName(section: indexPath.section)
let header = UICollectionReusableView()
if let headerCell = collectionView.dequeueReusableSupplementaryView(
ofKind: kind,
withReuseIdentifier: collectionViewHeaderFooterReuseIdentifier,
for: indexPath
) as? SectionHeaderForModelCell {
headerCell.labelTitle.text = seriesTitle
return headerCell
}
return header
default:
return UICollectionViewCell()
}
}
}
func collectionView(
_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath
) -> UICollectionViewCell {
var cell: UICollectionViewCell = UICollectionViewCell()
switch collectionView {
case self.collectionDevices:
let titleDevice = modelForDisplayDevices[indexPath.section].title
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
if let customCell = cell as? CustomCellForDevice {
customCell.labelTitle.text = titleDevice
return customCell
}
case self.collectionModels:
let cellTitle = getModelsTitle(section: indexPath.section, indexPath: indexPath.row)
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
if let customCell = cell as? CustomCellForModel {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(printHello))
customCell.addGestureRecognizer(tapGesture)
customCell.labelTitle.text = cellTitle
return customCell
}
default:
return cell
}
return cell
}
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int
) -> CGFloat {
return 0
}
@objc func printHello() {
print("1")
}
}
// MARK: - Render
extension MainRepairViewController: IMainRepairViewLogic {
func render(viewModel: [MainRepairModel.ViewModel.Device]) {
self.modelForDisplayDevices = viewModel
collectionDevices.reloadData()
collectionModels.reloadData()
// showModel()
}
func showModel() {
for device in modelForDisplayDevices {
print("\(device.title)")
if !device.series.isEmpty {
for series in device.series {
print("\(series.titleSeries)")
}
}
}
}
}
// MARK: Load data.
private extension MainRepairViewController {
@objc func fetchCatalog() {
// iterator?.fetchCatalog()
}
}