表格视图中的慢速/口吃滚动

Posted

技术标签:

【中文标题】表格视图中的慢速/口吃滚动【英文标题】:Slow/Stuttered scroll in tableview 【发布时间】:2016-03-21 23:53:13 【问题描述】:

我正在从字典数组 (tasks) 中加载大约 150 个元素,我可以将所有数据放入我的 tableview 中,但是当我滚动它时速度很慢。当我将我的一个函数的信息打印到控制台时,看起来每次滚动时我都会取回所有数据。这是我加载不好(即异步)还是我需要更改我的功能?

    func querySections() -> [String] 
        var sectionsArray = [String]()
        for task in tasks 
            let dueTimes = task.dueTime
            sectionsArray.append(dueTimes)
        
        let uniqueSectionsArray = Array(Set(sectionsArray.sort()))
//        print(uniqueSectionsArray)
        return uniqueSectionsArray
    


    func queryDueTimes(section:Int) -> [Task] 
        var sectionItems = [Task]()
        for task in tasks 
            let dueTimes = task.dueTime
            if dueTimes == querySections()[section] 
                sectionItems.append(task)
            
        
        print(sectionItems)
        return sectionItems
    



    // MARK: - Table view data source

    override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
        return querySections()[section]
    

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int 
        return querySections().count
    

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return queryDueTimes(section).count
    


    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCellWithIdentifier("TaskCell", forIndexPath: indexPath) as! TaskCell

        // Configure the cell...
        cell.selectionStyle = .None
        let times = queryDueTimes(indexPath.section)
        let task = times[indexPath.row]
        cell.label.text = task.title
        if task.done == true 
            cell.checkBox.image = UIImage(named: "checkedbox")
            cell.detailLabel.text = "Completed By: \(task.completedBy)"
            
            else 
            cell.checkBox.image = UIImage(named: "uncheckedbox")
            cell.detailLabel.text = ""
            

        cell.delegate = self
        return cell
    

基本上,在querySections 中,我将遍历每个任务的所有到期时间,然后将它们更改为一组数组,以便过滤掉所有重复项。这给了我所有的部分。对于queryDueTimes,我正在遍历任务并将它们匹配到一个部分。

我曾想过调用 viewDidLoad 中的函数,但这不起作用(当我尝试将它传递给另一个在函数之外更易于访问的空数组时,它一直给我一个空数组),我可以't access section (for queryDueTimes) in viewDidLoad (据我所知)。

更新 1: 我认为错误在我的最后。我说我的任务是一个数组数组,而它只是一个任务数组(一个具有每个任务所有属性的结构)。当我加载应用程序时,我将后端的所有任务附加到本地数组(“任务”)。我应该有一个数组来让它工作还是我可以以某种方式修改我的代码并让它工作?

更新 2:

当我打印 sectionTimestasksInSectionArray 时,它们是空数组。

    var sectionTimes = [String]()
    var tasksInSectionArray = [[Task]]()
    var tasks = [Task]() 
        didSet 
            tableView?.reloadData()
        
    

    func updateTableView() 
            sectionTimes = Set(tasks.map$0.dueTime).sort()
            tasksInSectionArray = sectionTimes.mapsection in tasks.filter$0.dueTime == section
            print(sectionTimes)
            print(tasksInSectionArray)
            tableView.reloadData()
        

override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
            return sectionTimes[section]
        

        override func numberOfSectionsInTableView(tableView: UITableView) -> Int 
            return sectionTimes.count
        

        override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
            return tasksInSectionArray[section].count
        


        override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
            let cell = tableView.dequeueReusableCellWithIdentifier("TaskCell", forIndexPath: indexPath) as! TaskCell

            // Configure the cell...
            cell.selectionStyle = .None
            let task = tasksInSectionArray[indexPath.section][indexPath.row]

【问题讨论】:

别猜了。不要猜测。使用仪器!它会准确地告诉您在滚动期间占用了哪些时间。然后你就会知道把注意力集中在哪里。 我仍然不确定如何使用它。对于使用 Swift for ios 进行开发,我还是很陌生。你能帮我在正确的方向上提供一两步吗? 不幸的是,看起来 DMan 正在通过目测解决您的问题。这很糟糕,因为学习使用 Instruments 会更好! :)))) 【参考方案1】:

如您所料,数据被一遍又一遍地加载和排序,而不仅仅是一次。保存querySelectionsqueryDueTimes 的结果并在表视图数据源方法中使用。

您可以在 viewDidLoad 中执行此操作 - 调用这两个函数一次并将结果分配给类级别的变量,然后调用 tableView.reloadData()(假设您有对表视图的引用)。

【讨论】:

我想我之前已经尝试过这个,因为我遇到了一个熟悉的问题。当我开始使用 cellForRow 时,我在前几行代码中遇到了问题。让时间,让任务。我可以将时间分配给 sectionTimes[indexPath.section](sectionTimes 是在班级级别),但我不能将任务分配给 times[indexPath.row]。【参考方案2】:
var sections: [String] = []
var data: [[Tasks]] = []

func updateTableView() 
    sections = Set(tasks.map  $0.dueTime ).sort()
    data = sections.map  section in tasks.filter  $0.dueTime == section  
    tableView.reloadData()


override func numberOfSectionsInTableView(tableView: UITableView) -> Int 
    return sections.count


override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return data[section].count


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    let task = data[indexPath.section][indexPath.row]

    // Cell configuration

这基本上是DMan所说的,但我已经为你做了一个例子。

【讨论】:

这可能不是您想要的,因此您可能需要根据自己的喜好对其进行排序。但通常这应该会加快速度。 对不起。我对此还是很陌生。也许我错误地沟通了,因为我遇到了错误。在 updateTableView() (data=...) 的第 2 行我收到一个错误,它无法将 [Task] 转换为 Task 的闭包结果类型。 别抱歉。每个人都会犯错,我应该因为我犯了一个错误而感到抱歉:p。我会编辑答案。 查看我的更新...您的解决方案与我最初给您的解决方案是正确的(我起初对我的解决方案有点困惑)。包含更多我的代码会有帮助吗? 回答您的编辑:如果您想要多个部分,“最简单”的方法是拥有一个二维数组,例如数组的数组。您可以改为创建字典或像以前一样每次手动计算它,但正如您已经注意到的那样效率不高。我的回答是否给出了另一个错误?还是有其他原因它不起作用?

以上是关于表格视图中的慢速/口吃滚动的主要内容,如果未能解决你的问题,请参考以下文章

UIScrollView 中的 UIView 中的 UITableView。滚动表格视图时也不要滚动滚动视图

表格单元格视图中的 iCarousel 视图根本不滚动

表格视图中的滚动视图分页

ios中带有表格视图的嵌套滚动视图

使表格视图中的 UITextField 可见滚动

UIScrollViewDelegate 中的委托方法不响应表格视图滚动事件