Лучше ли скрыть табличную ячейку или фильтр в источнике данных?(проблема производительности) - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть UITableViewController, где у меня есть ячейки, которые я хочу скрыть.

В настоящее время я скрываю ячейки с heightForRowAt, возвращающим 0, и cellForRowAt, возвращающим ячейку с isHidden = false.Но так как я использую это решение, я заметил, что приложение прокручивалось в моем tableView.

// Currently returning a height of 0 for hidden cells
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if let post = timeline?.postObjects?[indexPath.row], post.hidden ?? false {
        return 0.0
    }
    return UITableView.automaticDimension
}

// And a cell with cell.isHidden = false (corresponding to identifier "hiddenCell")
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let post = timeline?.postObjects?[indexPath.row] {
        if post.hidden ?? false {
            return tableView.dequeueReusableCell(withIdentifier: "hiddenCell", for: indexPath)
        } else {
            return (tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell).with(post: post, timelineController: self, darkMode: isDarkMode())
        }
    }
}

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

// Returning only the number of visible cells
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return timeline?.postObjects?.filter{!($0.hidden ?? false)}.count
}

// And creating cells for only visible rows
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let post = timeline?.postObjects?.filter{!($0.hidden ?? false)}[indexPath.row] {
        return (tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell).with(post: post, timelineController: self, darkMode: isDarkMode())
    }
}

Каков наилучший вариант?Скрытие ячеек при их создании (первое) или исключение их из списка (второе)?

Ответы [ 2 ]

0 голосов
/ 26 февраля 2019

Нет смысла иметь ячейки с размером 0. Лучше всего фильтровать ваш источник данных, но я бы посоветовал сохранить два массива одновременно.

Но обрабатывайте фильтрацию в другом месте.затем в число OfRowsInSection.


var filteredObjects = []

func filterObjects() {
    filteredObjects = timeline?.postObjects?.filter{!($0.hidden ?? false)}
}


// Returning only the number of visible cells
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return filteredObjects.count
}

// And creating cells for only visible rows
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let post = filteredObjects[indexPath.row] {
        return (tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell).with(post: post, timelineController: self, darkMode: isDarkMode())
    }
}

Я не знаю, как вы справляетесь с фильтрацией, но всякий раз, когда вы хотите применить свой фильтр, вы просто

filterObjects()
tableView.reloadData()
0 голосов
/ 26 февраля 2019

Я бы рекомендовал разрешить методам источника данных табличного представления работать с отфильтрованной версией timeline.Однако не делайте этого в методе cellForRowAt, потому что нам нужно сделать это один раз, но не для каждого рисунка ячейки.

Итак, вы можете объявить filteredTimeline и выполнить фильтр один разв методе viewDidLoad (например):

class TableViewController: UIViewController {
    // ...
    var filteredTimeline // as the same type of `timeline`


    override func viewDidLoad() {
        // ...

        filteredTimeline = timeline?.postObjects?.filter{!($0.hidden ?? false)}

        // ...
    }

    // Returning only the number of visible cells
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return filteredTimeline.count ?? 0
    }

    // And creating cells for only visible rows
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let post = filteredTimeline?.postObjects?.filter{!($0.hidden ?? false)}[indexPath.row] {
            return (tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell).with(post: post, timelineController: self, darkMode: isDarkMode())
        }
    }

    // ...
}

В случае лучшего места для filteredTimeline = timeline?.postObjects?.filter{!($0.hidden ?? false)}, чем viewDidLoad, вам может потребоваться позвонить tableView.reloadData().

Альтернатива, которую вы можете сделать:

, если вы считаете, что вам не нужен оригинал timeline, вы можете отфильтровать его сам:

timeline = timeline?.postObjects?.filter{!($0.hidden ?? false)}
tableView.reloadData()

и вам не понадобится дополнительный отфильтрованный массив.


Дополнительный совет:

В случае возврата 0.0 значения в методе heightForRowAt для определенногострока cellForRowAt даже не будет вызвана;Например:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 2
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return indexPath.row == 0 ?? 0.0 : 100.0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    // ...
}

На этом этапе cellForRowAt следует вызывать только один раз, поскольку высота для первого ряда 0.0.

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