微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

UITableView 上的用户交互阻止进程

如何解决UITableView 上的用户交互阻止进程

我有一个 TabelViewController。 TableViewCells 中的数据正在通过 tableview.reloadData() 以高频率(假设为 10 Hz)更新。到目前为止,这有效。但是当我滚动 TableView 时,更新会暂停,直到用户交互结束。我的应用程序中的所有其他进程也都暂停了。我该如何解决这个问题?

这是一个示例 TableViewController。如果您在模拟器上运行它并检查调试区域内的输出,您会注意到,当您滚动并按住 tableview 时,不仅图形(这里是标签)的更新被暂停,而且通知也被暂停。如果你在另一个类中有一个进程,情况也是如此。

有趣的是,如果您与 MapView 交互,则不会出现这种进程阻塞。我在这里错过了什么?

import UIKit

class TableViewController: UITableViewController {
    
    var text = 0
    var timer = Timer()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        NotificationCenter.default.addobserver(self,selector: #selector(self.recieveNotification),name: NSNotification.Name(rawValue: "testNotificatiion"),object: nil)
        
        scheduledTimerWithTimeInterval()
    }
    
    func scheduledTimerWithTimeInterval(){
        timer = Timer.scheduledTimer(timeInterval: 1/10,target: self,selector: #selector(self.updateCounting),userInfo: nil,repeats: true)
    }
    
    @objc func updateCounting(){
        text += 1
        
        let userInfo = ["test": text]
        
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "testNotificatiion"),object: nil,userInfo: userInfo)
        
        tableView.reloadData()
    }
    
    @objc func recieveNotification(notification: Notification){
        
        if let userInfo = notification.userInfo! as? [String: Int]
        {
            if let recieved = userInfo["test"] {
                print("Notification recieved with userInfo: \(recieved)")
            }
        }
    }
    
    // MARK: - Table view data source
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    override func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
        return 10
    }
    
    override func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var cell: UITableViewCell?
        cell = tableView.dequeueReusableCell(withIdentifier: "rightDetail",for: indexPath)
        cell?.detailTextLabel?.text = String(text)

        return cell!
    }
}

解决方法

在滚动 UITableView 时不会触发计时器。查看爱斯基摩人奎因 (Quinn The Eskimo) 的答案 here

将您的方法更改为这样,即使在滚动时也能正常工作。

func scheduleMyTimer() {
    let t = Timer(timeInterval: 1.0,repeats: true) { _ in
        self.updateCounting()
    }
    RunLoop.current.add(t,forMode: RunLoop.Mode.common)
}
当滚动 CoreLocation 时,

UITableView 回调也不会触发。这是一个解决方法。

来自 CLLocationManagerDelegate 的文档:

Core Location 在 runloop 上调用你的委托对象的方法 来自您初始化 CLLocationManager 的线程。那 线程本身必须有一个活动的运行循环,就像在你的 应用的主线程。

所以我改变了 CLLocationManager init:

class AppDelegate {
    var lm = CLLocationManager()
}

为此:

class AppDelegate {
    var lm: CLLocationManager!
    var thread: Thread!

    func didFinishLaunching() {
        thread = Thread {
            self.lm = CLLocationManager()

            Timer.scheduledTimer(withTimeInterval: 1,repeats: true) { (_) in
                // empty on purpose
            }
        
            RunLoop.current.run()

            // If no input sources or timers are attached
            // to the run loop,the run() method exits immediately,// so we add a Timer just before the call.

        }
        thread.start()
    }
}

然后,即使在滚动时,委托回调也会继续触发。 This 回答有帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。