在数据源中隐藏tableviewcell或过滤器更好吗? (性能问题)

时间:2019-02-26 18:09:24

标签: ios swift uitableview

我有一个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 :(得分:1)

我建议让表格查看数据源方法以处理经过{em>过滤的版本的beforeEach(() => { moxios.install(); moxios.stubRequest("https://jsonplaceholder.typicode.com/comments", { status: 200, response: [{ name: "Fetched #1" }, { name: "Fetched #2" }] }); }); afterEach(() => { moxios.uninstall(); }); it("can fetch a list of comments and display them", done => { const wrapped = mount( <Root> <App /> </Root> ); wrapped.find(".fetch-comments").simulate("click"); moxios.wait(() => { let request = moxios.requests.mostRecent(); request .respondWith({ status: 200, response: [ { name: "Fetched #1" }, { name: "Fetched #2" } ] }) .then(() => { wrapped.update(); console.log(wrapped.html()); expect(wrapped.find("li").length).toEqual(2); done(); wrapped.unmount(); }); }); }); 。但是,请勿在{{1​​}}方法中执行此操作,因为我们需要执行一次,但不必对每个单元格图形执行一次。

因此,您可以做的是声明timeline并在cellForRowAt方法中进行一次过滤(例如):

filteredTimeline

如果比起viewDidLoadclass 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 { // ... }

答案 1 :(得分:1)

大小为0的单元格是没有意义的。最好的选择是过滤数据源,但是我的建议是同时保留两个数组。

但是请在numberOfRowsInSection中的其他地方处理过滤。

cellForRowAt

我不知道您如何处理过滤器,但是只要您想应用过滤器,

0.0