Swift 3 中如何检查当前线程?

160

在Swift 3中,如何检查当前线程?

在以前的Swift版本中,可以通过以下方式检查当前线程是否为主线程:

NSThread.isMainThread()

这里大部分的回答已经不再适用于(Swift 5+)。在Swift 5中,Thread.isMainThread只是一个警告(并没有实际作用),而在Swift 6中将会变成一个错误。 - RobMac
7个回答

286

看起来在Swift 3中只需使用Thread.isMainThread即可。


142

Thread.isMainThread会返回一个布尔值,指示您当前是否在主UI线程上。但它不会提供当前线程的信息,仅告诉您是否在主线程上。

Thread.current将返回您目前正在运行的线程。


42

我制作了一个扩展程序,可以打印线程和队列:

extension Thread {
    class func printCurrent() {
        print("\r⚡️: \(Thread.current)\r" + ": \(OperationQueue.current?.underlyingQueue?.label ?? "None")\r")
    }
}

Thread.printCurrent()

执行结果将会是:

⚡️: <NSThread: 0x604000074380>{number = 1, name = main}
: com.apple.main-thread

同时建议使用以下内容:

extension DispatchQueue {
    /// - Parameter closure: Closure to execute.
    func dispatchMainIfNeeded(_ closure: @escaping VoidCompletion) {
        guard self === DispatchQueue.main && Thread.isMainThread else {
            DispatchQueue.main.async(execute: closure)
            return
        }

        closure()
    }
}

DispatchQueue.main.dispatchMainIfNeeded { ... }

33

Swift 4及以上版本:

Thread.isMainThread返回Bool值,表示用户是否在主线程上,如果有人想要打印队列/线程的名称,可以使用此扩展。

extension Thread {

    var threadName: String {
        if let currentOperationQueue = OperationQueue.current?.name {
            return "OperationQueue: \(currentOperationQueue)"
        } else if let underlyingDispatchQueue = OperationQueue.current?.underlyingQueue?.label {
            return "DispatchQueue: \(underlyingDispatchQueue)"
        } else {
            let name = __dispatch_queue_get_label(nil)
            return String(cString: name, encoding: .utf8) ?? Thread.current.description
        }
    }
}

使用方法:

print(Thread.current.threadName)

2
__dispatch_queue_get_label 不是 Swift 标准库的一部分,它只在 Apple 平台专用的框架中可用。例如,在 Ubuntu 上无法调用它。 - Xander Dunn
__dispatch_queue_get_label(nil) 终于有东西可以用了,谢谢! - J. Doe

17

Swift 5+

通常,我们只需要知道代码被分派到哪个队列。因此,我将threadNamequeueName分别放入不同的属性中,以使它更加清晰。

extension Thread {
    var threadName: String {
        if isMainThread {
            return "main"
        } else if let threadName = Thread.current.name, !threadName.isEmpty {
            return threadName
        } else {
            return description
        }
    }
    
    var queueName: String {
        if let queueName = String(validatingUTF8: __dispatch_queue_get_label(nil)) {
            return queueName
        } else if let operationQueueName = OperationQueue.current?.name, !operationQueueName.isEmpty {
            return operationQueueName
        } else if let dispatchQueueName = OperationQueue.current?.underlyingQueue?.label, !dispatchQueueName.isEmpty {
            return dispatchQueueName
        } else {
            return "n/a"
        }
    }
}

使用案例:

DispatchQueue.main.async {
   print(Thread.current.threadName)
   print(Thread.current.queueName)
}
// main
// com.apple.main-thread
DispatchQueue.global().async {
   print(Thread.current.threadName)
   print(Thread.current.queueName)
}
// <NSThread: 0x600001cd9d80>{number = 3, name = (null)}
// com.apple.root.default-qos

13

使用GCD时,可以使用dispatchPrecondition来检查进一步执行所必需的调度条件。如果您想要确保代码在正确的线程上执行,这将非常有用。例如:

DispatchQueue.main.async {
    dispatchPrecondition(condition: .onQueue(DispatchQueue.global())) // will assert because we're executing code on main thread
}

5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接