我正在调用一些代码来查询和更新CallKit调用扩展,偶尔我会看到挂起,调用超时.我想我应该把它从主线程上移开,这样它就不会阻塞UI,但实际上情况并非如此吗?

用户界面被阻塞了,我不知道是下面这段代码,还是别的什么.

以下是查询函数:

    private func queryCallExtensionStatusWithDispatchGroup() {
        let dg = DispatchGroup()
        dg.enter()
        self.doQueryCallExtensionStatusWithDispatchGroup(dispatchGroup: dg)
        Logger.trace(TAG + "queryCallExtensionStatusWithDispatchGroup() WAITING .... ")
        let dispatchTimeoutResult = dg.wait(timeout:  DispatchTime.now() + DispatchTimeInterval.seconds(30))
        if dispatchTimeoutResult == .timedOut {
            Logger.info(TAG + "queryCallExtensionStatusWithDispatchGroup() TIMED OUT")
        } else {
            Logger.trace(TAG + "queryCallExtensionStatusWithDispatchGroup() LEFT")
        }
    }


private func doQueryCallExtensionStatusWithDispatchGroup(dispatchGroup:DispatchGroup)  {
<snip>
    dispatchGroup.leave() 
}

以及它的调用:

private let callExtensionQueue = DispatchQueue(label: "com.appname.serialQueue")

...
callExtensionQueue.async {
    self!.queryCallExtensionStatusWithDispatchGroup()
}

推荐答案

您的代码片段将阻止callExtensionQueue使用的辅助线程,而不是主线程.

因此,除非您在其他地方有大约sync个分派到callExtensionQueue(或一些不寻常的线程爆炸场景),否则上面的代码不会阻塞主线程.

你的问题可能出在其他地方.


在希望确保不会意外调用主队列中的函数的情况下,可以添加一个dispatchPrecondition,这样,如果意外地从主队列中调用此函数,则在调试版本中会收到一条警告:

private func queryCallExtensionStatusWithDispatchGroup() {
    dispatchPrecondition(condition: .notOnQueue(.main))

    let group = DispatchGroup()
    group.enter()
    doQueryCallExtensionStatus {
        group.leave()
    }
    logger.trace("\(#function) WAITING .... ")
    let result = group.wait(timeout: .now() + .seconds(30))
    if result == .timedOut {
        logger.info("\(#function) TIMED OUT")
    } else {
        logger.trace("\(#function) LEFT")
    }
}

另外,在上面,不是将调度组传递给被调用的函数(这两个函数不必要地纠缠在一起),标准技术是一个完成处理程序闭包参数(如果需要,您可以将其设置为可选的):

private func doQueryCallExtensionStatus(completion: (() -> Void)? = nil) {
    …
    completion?()
}

这样,所有DispatchGroup个相关代码都被隔离到单个函数queryCallExtensionStatusWithDispatchGroup中.

Swift相关问答推荐

Swift C外部实现的Task / Future类类型

了解SWIFT中的命名VS位置函数调用

如何使用AsyncTimerSequence获取初始时钟,然后在指定的时间间隔内开始迭代?

如何获取嵌套数组中项的路径以修改数组?

如何在SwiftUI中做出适当的曲线?

Swift中从头开始的基本HTTP客户端

关闭 SwiftUI TabView 中的子视图

在 init(from decoder: Decoder) 方法中访问原始 JSON 数据

如何在 swift 5.0 中获取当前行

Firebase removeObserver 在 Swift 5 中不起作用

将基于MyProtocol的泛型函数的参数更改为使用存在的any MyProtocol或some MyProtocol是否会受到惩罚?

`@available` 属性在 macOS 版本上被错误地限制

判断 Swift 程序是否正在输出到终端

无法从自定义动态框架(Swift)访问类

在 Swift 中将两个字节的 UInt8 数组转换为 UInt16

AES 加密和解密

Alamofire:如何全局处理错误

UIButton 标题左对齐问题 (iOS/Swift)

Xcode6 中的 Swift 类与 Cocoa Touch 类

在这个例子中美元符号有什么作用?