我有一个 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())
}
}
什么是最好的选择?在生成单元格时隐藏单元格(第一次)或将它们从列表中排除(第二次)?
最佳答案
我建议让 TableView 数据源方法处理 timeline
的filtered 版本。但是,不要在 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?.postObjects?.filter{!($0.hidden ?? false)}
tableView.reloadData()
并且您将不需要额外的过滤数组。
额外提示:
如果在 heightForRowAt
方法中为特定行返回 0.0
值,甚至不会调用 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
。
关于ios - 在数据源中隐藏 tableviewcell 或过滤器更好吗? (性能问题),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54891640/