ПОЧЕМУ ВСЕГДА инициализировать 19 ячеек? - PullRequest
0 голосов
/ 24 октября 2019

Я изучаю TableView в Swift. Мой учитель задает мне вопрос: «У вас 20 ячеек, но на экране отображается 3 ячейки. Сколько ячеек было инициализировано и почему?

Это мой код. Я пробовал использовать более 20 ячеек, этовсегда инициализировал 19 ячеек. Может кто-нибудь объяснить мне, почему? Большое спасибо, я тестирую на iPhone 11 ProMax, iOS 13.1

override func viewDidLoad() {
        super.viewDidLoad()
        myTable.register(UINib(nibName: "ContactCell", bundle: nil), forCellReuseIdentifier: "ContactCell")
        myTable.dataSource = self
        myTable.delegate = self
    }
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 20

    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ContactCell", for: indexPath) as! ContactCell
        cell.textLabel?.text = "Superhero"

        return cell
    }
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return myTable.frame.size.height / 3.0
    }
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print(indexPath.section)
        print(indexPath.row)
    }

Этот код в другом файле

    class ContactCell: UITableViewCell {

        @IBOutlet weak var cellShow: UIView!
        override func awakeFromNib() {
            super.awakeFromNib()
            print("awakeFromNib")
        }

        override func setSelected(_ selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)

        }  
    }

1 Ответ

0 голосов
/ 24 октября 2019

Из документов Apple (https://developer.apple.com/documentation/uikit/uitableviewdelegate/1614998-tableview):

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

Во время макета начнется заполнение табличного представления. процесс, размеры для элементов определяются.В зависимости от начальной высоты вашей ячейки и высоты табличного представления, сначала может быть вызван heightForRowAt для строк, которые могут появиться , затем для строк, которые вероятно появится, затем для строк, которые появится (и строк, которые могут быть просто за кадром).

Добавьте оператор print() к вашему heightForRowAtfunc следующим образом:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

    // add this line
    print(indexPath)

    return myTable.frame.size.height / 3.0
}

В моем быстром тесте, если 7 высота по умолчанию строки будут соответствовать в зависимости от высоты моего представления таблицы, я вижу это в выходных данных отладки:

[0, 0]
[0, 0]
[0, 0]
[0, 1]
[0, 1]
[0, 1]
[0, 2]
[0, 2]
[0, 2]
[0, 3]
[0, 3]
[0, 3]
[0, 4]
[0, 4]
[0, 4]
[0, 5]
[0, 5]
[0, 5]
[0, 6]
[0, 6]
[0, 6]

Как видите, 7 ячеек инициализируются, heightForRowAt вызывается 3 раза для каждой ячейки.

Редактировать: тьфу ... на основе нуля ... изменено неправильно 6 исправить 7


Дополнительные примечания ...

Если вы установите .estimatedRowHeight, например:

myTable.estimatedRowHeight = 150

, вы увидите меньше инициализируемых ячеек и с:

myTable.estimatedRowHeight = 10

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

Также, если вы хотите немного больше узнать о том, как ячейки используются повторно , добавьте это в ваш обработчик didSelectRowAt (это всего лишь функция отладки / разработки, вероятно, не полезная для производственного кода):

let reusableCells = tableView.value(forKey: "_reusableTableCells")
print(reusableCells as Any)

В моем случае (без настройки .estimatedRowHeight) я получаю:

Optional({
    ContactCell =     (
        "<MyTest.ContactCell: 0x7fd0ccc295b0; baseClass = UITableViewCell; frame = (0 300; 295 100); text = 'Superhero'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x6000010fecc0>>",
        "<MyTest.ContactCell: 0x7fd0ccc2a2a0; baseClass = UITableViewCell; frame = (0 400; 295 100); text = 'Superhero'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x6000010ff0c0>>",
        "<MyTest.ContactCell: 0x7fd0ccc2ad90; baseClass = UITableViewCell; frame = (0 500; 295 100); text = 'Superhero'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x6000010ff4a0>>",
        "<MyTest.ContactCell: 0x7fd0ccc2ba80; baseClass = UITableViewCell; frame = (0 600; 295 100); text = 'Superhero'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x6000010ff8a0>>"
    );
})

Обратите внимание, что количество ячеек в «пуле многократного использования» будет меняться при прокрутке вверхи вниз.

Другое Редактирование:

Также стоит поэкспериментировать с ... измените эту строку в cellForRowAt, с:

cell.textLabel?.text = "Superhero"

на:

cell.textLabel?.text = "Superhero \(indexPath.row)"

Теперь, когда вы выбираете строку и распечатываете «reusableCells», вы можете видеть, какие ячейки действительно находятся в «пуле». Мой результат меняется на:

Optional({
    ContactCell =     (
        "<MyTest.ContactCell: 0x7fef77608330; baseClass = UITableViewCell; frame = (0 300; 295 100); text = 'Superhero 3'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003d36d20>>",
        "<MyTest.ContactCell: 0x7fef776091b0; baseClass = UITableViewCell; frame = (0 400; 295 100); text = 'Superhero 4'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003d37120>>",
        "<MyTest.ContactCell: 0x7fef7760a030; baseClass = UITableViewCell; frame = (0 500; 295 100); text = 'Superhero 5'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003d37500>>",
        "<MyTest.ContactCell: 0x7fef7760aeb0; baseClass = UITableViewCell; frame = (0 600; 295 100); text = 'Superhero 6'; clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003d37920>>"
    );
})

Показывает, что ячейки для строк 4, 5, 6 и 7 (как показано в свойстве text = - опять же, начиная с нуля) были инициализированы и находятся в «пуле повторного использования».

...