如何在swift 3

时间:2016-09-18 01:10:51

标签: swift swift3

我们在swift 2.2中有这样的功能,用于使用当前运行的线程打印日志消息:

func MyLog(_ message: String) {
    if Thread.isMainThread {
        print("[MyLog]", message)
    } else {
        let queuename = String(UTF8String: dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL))! // Error: Cannot convert value of type '()' to expected argument type 'DispatchQueue?'
        print("[MyLog] [\(queuename)]", message)
    }
}

这些代码不再在swift 3.0中编译。我们现在如何获得队列名称?

问题是如何识别两个线程在同一个线程中的位置:Check if on correct dispatch queue in Swift 3。接受的答案建议使用setSpecific关联"标签"使用已创建的队列。但是,这并没有解决问题,因为我们想知道队列名称。队列可能不一定是由我们自己创建的。

6 个答案:

答案 0 :(得分:31)

Brent Royal-Gordon 在他的message lists.swift.org 中提及它在当前设计中的一个漏洞,但你可以使用这个可怕的解决方法。

  func currentQueueName() -> String? {
        let name = __dispatch_queue_get_label(nil)
        return String(cString: name, encoding: .utf8)
    }

答案 1 :(得分:5)

如果你不喜欢不安全的指针和c-strings,还有另一个安全的解决方案:

if let currentQueueLabel = OperationQueue.current?.underlyingQueue?.label {
    print(currentQueueLabel)
    // Do something...
}

我不知道currentQueueLabelnil时的任何情况。

答案 2 :(得分:2)

Now DispatchQueue has label property

在创建时分配给调度队列的标签。

var label: String { get } 

它似乎从一开始就存在,也许没有通过公共API公开。

macOS 10.10+

并且请仅使用此标签来获取人类可读的标签。不识别每个GCDQ。

如果要检查代码是否在某些GCDQ上运行,可以使用dispatchPrecondition(...) function

答案 3 :(得分:1)

这是一个提供一些安全性的包装器类(from here修订版):

import Foundation

/// DispatchQueue wrapper that acts as a reentrant to a synchronous queue;
/// so callers to the `sync` function will check if they are on the current
/// queue and avoid deadlocking the queue (e.g. by executing another queue
/// dispatch call). Instead, it will just execute the given code in place.
public final class SafeSyncQueue {

    public init(label: String, attributes: DispatchQueue.Attributes) {
        self.queue = DispatchQueue(label: label, attributes: attributes)
        self.queueKey = DispatchSpecificKey<QueueIdentity>()
        self.queue.setSpecific(key: self.queueKey, value: QueueIdentity(label: self.queue.label))
    }

    // MARK: - API

    /// Note: this will execute without the specified flags if it's on the current queue already
    public func sync<T>(flags: DispatchWorkItemFlags? = nil, execute work: () throws -> T) rethrows -> T {
        if self.currentQueueIdentity?.label == self.queue.label {
            return try work()
        } else if let flags = flags {
            return try self.queue.sync(flags: flags, execute: work)
        } else {
            return try self.queue.sync(execute: work)
        }
    }

    // MARK: - Private Structs

    private struct QueueIdentity {
        let label: String
    }

    // MARK: - Private Properties

    private let queue: DispatchQueue
    private let queueKey: DispatchSpecificKey<QueueIdentity>

    private var currentQueueIdentity: QueueIdentity? {
        return DispatchQueue.getSpecific(key: self.queueKey)
    }

}

答案 4 :(得分:0)

这对我最有用:

/// The name/description of the current queue (Operation or Dispatch), if that can be found. Else, the name/description of the thread.
public func queueName() -> String {
    if let currentOperationQueue = OperationQueue.current {
        if let currentDispatchQueue = currentOperationQueue.underlyingQueue {
            return "dispatch queue: \(currentDispatchQueue.label.nonEmpty ?? currentDispatchQueue.description)"
        }
        else {
            return "operation queue: \(currentOperationQueue.name?.nonEmpty ?? currentOperationQueue.description)"
        }
    }
    else {
        let currentThread = Thread.current
        return "UNKNOWN QUEUE on thread: \(currentThread.name?.nonEmpty ?? currentThread.description)"
    }
}



public extension String {

    /// Returns this string if it is not empty, else `nil`.
    public var nonEmpty: String? {
        if self.isEmpty {
            return nil
        }
        else {
            return self
        }
    }
}

答案 5 :(得分:-2)

此方法适用于Operation Queue和Dispatch Queue。

    func printCurrnetQueueName()
    {
        print("Perform Operation \(String(describing: OperationQueue.current?.name!))")
    }