Зачем возвращать ноль tableViewCell для параметра cellProvider UITableViewDiffableDataSource? - PullRequest
0 голосов
/ 11 июня 2019

iOS 13 имеет несколько новых API для обработки tableView, и одна интересная область API - это cell поставщик параметр из UITableViewDiffableDataSource

    public typealias CellProvider = (UITableView, IndexPath, ItemIdentifierType) -> UITableViewCell?

Когда было бы целесообразно вернуть a nil UITableViewCell сюда?

1 Ответ

1 голос
/ 11 июня 2019

Таким образом, этот API все еще находится на стадии бета-тестирования, что означает, что документация не завершена.

В нем говорится:

Эта документация содержит предварительную информацию об API или технологии в разработке.Эта информация может быть изменена, и программное обеспечение, реализованное в соответствии с этой документацией, должно быть протестировано с окончательным программным обеспечением операционной системы.

TLDR - На данный момент, если вы создаете UITableView и используетеUITableViewDiffableDataSource, который возвращает ноль, ваше приложение будет аварийно завершено.

Тем не менее, этот пост в блоге содержит некоторые новые подробности.Это не упоминает ничего о возврате ноля для клетки, хотя.

Вы также можете взглянуть на этот сеанс WWDC.Примерно через 15 минут вы увидите, что пример кода выдает фатальную ошибку, если ячейка не может быть создана.

Используя блог выше, я сделал простой tableView в Xcode 11 следующим образом:

class ViewController: UIViewController {

    enum Section: CaseIterable {
        case friends
        case family
        case coworkers
    }

    struct Contact: Hashable {
        var name: String
        var email: String
    }

    struct ContactList {
        var friends: [Contact]
        var family: [Contact]
        var coworkers: [Contact]
    }

    private let tableView = UITableView()
    private let cellReuseIdentifier = "cell"
    private lazy var dataSource = makeDataSource()

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(UITableViewCell.self,
                           forCellReuseIdentifier: cellReuseIdentifier
        )

        tableView.dataSource = dataSource

        view.addSubview(tableView)

        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

        loadData()
    }


    func makeDataSource() -> UITableViewDiffableDataSource<Section, Contact> {
        let reuseIdentifier = cellReuseIdentifier

        return UITableViewDiffableDataSource(
            tableView: tableView,
            cellProvider: {  tableView, indexPath, contact in
                let cell = tableView.dequeueReusableCell(
                    withIdentifier: reuseIdentifier,
                    for: indexPath
                )

                cell.textLabel?.text = contact.name
                cell.detailTextLabel?.text = contact.email
                return cell
            }
        )
    }

    func update(with list: ContactList, animate: Bool = true) {
        let snapshot = NSDiffableDataSourceSnapshot<Section, Contact>()
        snapshot.appendSections(Section.allCases)

        snapshot.appendItems(list.friends, toSection: .friends)
        snapshot.appendItems(list.family, toSection: .family)
        snapshot.appendItems(list.coworkers, toSection: .coworkers)

        dataSource.apply(snapshot, animatingDifferences: animate)
    }

    func loadData() {
        let friends = [
            Contact(name: "Bob", email: "Bob@gmail.com"),
            Contact(name: "Tom", email: "Tom@myspace.com")
        ]

        let family = [
            Contact(name: "Mom", email: "mom@aol.com"),
            Contact(name: "Dad", email: "dad@aol.com")
        ]

        let coworkers = [
            Contact(name: "Mason", email: "tim@something.com"),
            Contact(name: "Tim", email: "mason@something.com")
        ]

        let contactList = ContactList(friends: friends, family: family, coworkers: coworkers)
        update(with: contactList, animate: true)
    }
}

Все отлично загружается, поэтому я решил посмотреть, что произойдет, если я верну nil для ячейки,Я добавил этот код в UITableViewDiffableDataSource:

if contact.name == "Bob" {
    return nil
}

Это закончилось тем, что вызвало сбой:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource returned a nil cell for row at index path: <NSIndexPath: 0xd6d99b18b93a5a0e> {length = 2, path = 0 - 0}. Table view: <UITableView: 0x7f8d30006200; frame = (-207 -448; 414 896); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x60000239de00>; layer = <CALayer: 0x600002dd0ec0>; contentOffset: {0, 0}; contentSize: {414, 264}; adjustedContentInset: {0, 0, 0, 0}; dataSource: <_TtGC5UIKit29UITableViewDiffableDataSourceOC5iOS1314ViewController7SectionVS2_7Contact_: 0x600002ffc520>>, dataSource: <_TtGC5UIKit29UITableViewDiffableDataSourceOC5iOS1314ViewController7SectionVS2_7Contact_: 0x600002ffc520>' 

На самом деле просто возвращение nil (без ячейки вообще) также вызывает сбой каккак только источник данных применяет обновление.Так что на данный момент, насколько я могу судить, возврат nil не является реальным вариантом, так как он вызывает сбой.

Вы можете оформить полный проект на github.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...