Как правильно расположить UICollectionView при обновлении UITableView внутри его разделов? - PullRequest
0 голосов
/ 11 апреля 2020

У меня есть контроллер вида, который состоит из UICollectionView с 3 секциями (каждая с UITableView внутри). Первый раздел довольно динамический c с данными, загруженными асинхронно из Интернета и вставляемыми методом self.tableView.insertItems(). Первые разделы обновляются правильно, и элементы добавляются в представление, но другие разделы не перемещаются, пока я не прокручиваю представление (Разделы 2 и 3 правильно переходят в нижнюю часть представления при прокрутке).

Итак, при запуске I в конечном итоге с результатом ниже (изображение). Конечно, использование self.collectionView.reloadData() сразу после self.tableView.insertItems() работает, но мне кажется немного странным. Может кто-нибудь указать мне на лучшее решение? Я могу предоставить пример проекта, если необходимо.

enter image description here

class ViewController: BaseViewController {
    static let firstCellId = "firstCellId"
    static let secondCellId = "secondCellId"
    static let thirdCellId = "thirdCellId"
    private weak var collectionView: UICollectionView!

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationItem.title = "Title"
        self.setupCollectionView()

    private func setupCollectionView() {
        let flowLayout = UICollectionViewFlowLayout()
        flowLayout.estimatedItemSize = CGSize(width: self.view.frame.width, height: 1.0)
        flowLayout.scrollDirection = .vertical
        flowLayout.minimumInteritemSpacing = 0.0
        flowLayout.minimumLineSpacing = 0.0
        let collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: flowLayout)
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.image = UIImage(named: "Background")
        collectionView.backgroundView = imageView
        let blurEffect = UIBlurEffect(style: .dark)
        let visualEffectView = UIVisualEffectView(effect: blurEffect)
        collectionView.backgroundView?.addSubview(visualEffectView)
        visualEffectView.fillSuperview()
        collectionView.alwaysBounceVertical = true
        collectionView.register(
            LibrarySectionHeaderView.self,
            forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
            withReuseIdentifier: LibrarySectionHeaderView.librarySectionHeaderId
        )
        collectionView.register(FirstTableViewCell.self, forCellWithReuseIdentifier: ViewController.firstCellId)
        collectionView.register(SecondTableViewCell.self, forCellWithReuseIdentifier: ViewController.secondCellId)
        collectionView.register(ThirdTableViewCell.self, forCellWithReuseIdentifier: ViewController.thirdCellId)
        self.view.addSubview(collectionView)
        self.collectionView = collectionView
        self.collectionView.translatesAutoresizingMaskIntoConstraints = false
        self.collectionView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        self.collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
        self.collectionView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
        self.collectionView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
        self.collectionView.delegate = self
        self.collectionView.dataSource = self
    }
}

// MARK: - UICollectionViewDelegateFlowLayout
extension ViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize(width: self.view.frame.width, height: 61.0)
    }
}

extension ViewController: UICollectionViewDataSource {
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 3
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: LibrarySectionHeaderView.librarySectionHeaderId, for: indexPath) as! LibrarySectionHeaderView
        switch indexPath.section {
        case 0:
            header.uiLabel.text = "Section 1"
        case 1:
            header.uiLabel.text = "Section 2"
        case 2:
            header.uiLabel.text = "Section 3"
        default:
            fatalError("Unsupported section index.")
        }
        return header
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        switch indexPath.section {
        case 0:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ViewController.firstCellId, for: indexPath) as! FirstTableViewCell
            self.firstTableViewCell = cell
            cell.setTableViewDelegates(dataSourceDelegate: self.firstSource, viewDelegate: self.firstSource)
            return cell
        case 1:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ViewController.secondCellId, for: indexPath) as! SecondTableViewCell
            cell.setTableViewDelegates(dataSourceDelegate: self.secondSource, viewDelegate: self.secondSource)
            return cell
        case 2:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ViewController.thirdTableCellId, for: indexPath) as! ThirdTableViewCell
            cell.setTableViewDelegates(dataSourceDelegate: self.thirdSource, viewDelegate: self.thirdSource)
            return cell
        default:
            fatalError("Unsupported section index!")
        }
    }
}

FirstTableViewCell в основном похож на Second:

class SecondTableViewCell: UICollectionViewCell {
    static let firstSubCellId = "firstSubCellId"
    lazy var width: NSLayoutConstraint = {
        let width = self.contentView.widthAnchor.constraint(equalToConstant: self.bounds.size.width)
        width.isActive = true
        return width
    }()
    private weak var tableView: ContentSizedTableView!

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.setupTableView()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupTableView() {
        let tableView = ContentSizedTableView(frame: self.frame, style: .plain)
        tableView.backgroundColor = .clear
        tableView.isScrollEnabled = false
        tableView.register(SecondTableViewRowCell.self, forCellReuseIdentifier: SecondTableViewCell.firstSubCellId)
        self.contentView.translatesAutoresizingMaskIntoConstraints = false
        self.contentView.addSubview(tableView)
        self.tableView = tableView
        self.tableView.translatesAutoresizingMaskIntoConstraints = false
        self.tableView.topAnchor.constraint(equalTo: self.contentView.topAnchor).isActive = true
        self.tableView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor).isActive = true
        self.tableView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor).isActive = true
        self.tableView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor).isActive = true
        tableView.separatorStyle = .singleLine
        tableView.separatorColor = .tableSeparatorColor
    }

    override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
        self.width.constant = bounds.size.width
        return self.contentView.systemLayoutSizeFitting(CGSize(width: targetSize.width, height: 1.0))
    }

    func deselectLastSelectedRow() {
        guard let lastRow = self.tableView.indexPathForSelectedRow else { return }
        self.tableView.deselectRow(at: lastRow, animated: true)
    }
}
class ContentSizedTableView: UITableView {
    override init(frame: CGRect, style: UITableView.Style) {
        super.init(frame: frame, style: style)
        self.estimatedRowHeight = UITableView.automaticDimension
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override var contentSize: CGSize {
        didSet {
            self.invalidateIntrinsicContentSize()
        }
    }
    override var intrinsicContentSize: CGSize {
        self.layoutIfNeeded()
        return CGSize(width: UIView.noIntrinsicMetric, height: self.contentSize.height)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...