首页 > 解决方案 > 使用 RunLoop.current.run 清理 SimplePing 代码

问题描述

我从 Apple 找到了SimplePing库,并希望在 SwiftUI 项目中使用它。

要使用我在线编码的库,它工作正常。start功能如下:

public func start(hostName: String) {
    
    let pinger = SimplePing(hostName: "192.168.178.20")
    pinger.delegate = self
    pinger.start()
    
    var count = 5
    repeat {
        if (self.canStartPinging) {
            pinger.send(with: nil)
            count-=1                
            if count == 0{
                self.canStartPinging = false
                break
            }
        }
        RunLoop.current.run(mode: RunLoop.Mode.default, before: NSDate.distantFuture)
    } while(true)

我真的不明白为什么我需要这RunLoop.current.run(mode: RunLoop.Mode.default, before: NSDate.distantFuture)条线。当我删除它时,不会调用 SimplePing 的代表。

如何简化此代码并在不阻塞主线程的情况下使用它?

标签: iosswift

解决方案


run(mode:before:)那里允许运行循环在这个循环旋转时处理事件repeatwhile这是一种使阻塞循环允许在运行循环上发生的事情的方法。

您还没有共享设置的代码canStartPinging,但我猜至少SimplePingDelegate方法didStartWithAddress设置了它。因此,如果您在没有调用 that 的情况下在主线程上旋转run(mode:before:),则SimplePing委托方法可能永远不会有机会被调用。通过添加该run调用,至少委托方法可以运行。

你对这整个旋转和呼叫模式的怀疑run(mode:before:)是有道理的。这是非常低效的模式。它应该被淘汰。

如果这是一个标准的 Swift 项目,我建议只使用委托协议模式就可以了。由于这是 Swift UI,我建议将其重构为 Combine Publisher,然后您可以将其集成到您的 SwiftUI 项目中。


推荐阅读