如何在swift 3中获取当前队列名称

如何在swift 3中获取当前队列名称,swift,swift3,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))! //

我们在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中编译。现在如何获取队列名称

正如布伦特·罗亚尔·戈登(Brent Royal Gordon)在他的onlists.swift.org中提到的,这是当前设计中的一个漏洞,但你可以使用这种可怕的解决方法

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

如果您不喜欢不安全的指针和c字符串,还有另一个安全的解决方案:

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

我不知道在什么情况下,
currentQueueLabel
将为
nil

这对我最合适:

///当前队列(操作或调度)的名称/描述(如果可以找到)。否则,线程的名称/描述。
public func queueName()->字符串{
如果让currentOperationQueue=OperationQueue.current{
如果让currentDispatchQueue=currentOperationQueue.underlyingQueue{
返回“调度队列:\(currentDispatchQueue.label.nonEmpty??currentDispatchQueue.description)”
}
否则{
返回“操作队列:\(currentOperationQueue.name?.nonEmpty??currentOperationQueue.description)”
}
}
否则{
让currentThread=Thread.current
返回“线程上的未知队列:\(currentThread.name?.nonEmpty??currentThread.description)”
}
}
公共扩展字符串{
///如果该字符串不为空,则返回该字符串,否则返回“nil”。
公共变量非空:字符串{
如果我是空的{
归零
}
否则{
回归自我
}
}
}

此方法适用于
操作队列
调度队列

func printCurrnetQueueName()
{
    print(Thread.current.name!)
} 

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

<代码>导入基础 ///充当同步队列重入器的DispatchQueue包装器; ///因此,`sync`函数的调用者将检查他们是否处于当前状态 ///排队并避免死锁队列(例如,通过执行另一个队列 ///调度电话)。相反,它只在适当的位置执行给定的代码。 公共最终类安全同步队列{ public init(标签:String,属性:DispatchQueue.attributes){ self.queue=DispatchQueue(标签:标签,属性:属性) self.queueKey=DispatchSpecificKey() self.queue.setSpecific(键:self.queueKey,值:QueueIdentity(标签:self.queue.label)) } //标记:-API ///注意:如果它已经在当前队列中,那么它将在没有指定标志的情况下执行 公共函数同步(标志:DispatchWorkItemFlags?=nil,执行工作:()抛出->T)重试->T{ 如果self.currentQueueIdentity?.label==self.queue.label{ 返回试用工作() }如果let flags=flags,则为else{ 返回try self.queue.sync(标志:标志,执行:工作) }否则{ 返回try self.queue.sync(执行:工作) } } //MARK:-私有结构 私有结构队列标识{ 让标签:字符串 } //马克:私人物业 私有let队列:DispatchQueue 私有let queueKey:DispatchSpecificKey private var currentQueueIdentity:QueueIdentity{ 返回DispatchQueue.getSpecific(键:self.queueKey) } }

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


它似乎从一开始就存在,可能没有通过公共API公开

macOS 10.10+
请仅用于获取人类可读的标签。不识别每个GCDQ


如果您想检查您的代码是否在某些GCDQ上运行,您可以使用。

现在可能重复。@Eonil:这应该作为答案发布。@MartinR谢谢。这个答案对我很有用:如果队列不是我们自己创建的,那么标签是什么?你看到这个问题了吗?有关系吗@克林。标签将类似于“com.apple.main thread”。2.这是关于测试的,这是非常相关的,但是对于你的问题没有直接的答案。这个解决方案似乎不能正常工作。对于同一个队列,
OperationQueue.current?.underyingqueue?.label
返回“com.apple.main thread”,而
String(cString:\u dispatch\u queue\u get\u label(nil),编码:.utf8)
返回“mydispatch queuelabel”@jakehawken,我尝试过了。我刚刚把
print(OperationQueue.current)
放在
里面,用options
完成了启动,
current
不是零。它就像:
{name='NSOperationQueue Main Queue'}
。因此,可能所有内容都在某个操作的上下文中。这仅适用于专门为操作队列创建的调度队列,而且,仅当这些调度队列当前处于活动状态时才会触发,因为它们的操作队列正在积极执行操作。如果不满足这些条件中的任何一个,您将得到一个
nil
标签。举个例子:您自己的调度队列,或者您自己的块提交到任何队列期间。刚刚尝试了解决方案,但需要额外的时间,例如1-2秒来执行单行。通常,创建DispatchSpecificKey作为实例变量是不安全的。键通过它们在内存中的地址进行比较,如果创建并释放多个键,它们可能最终共享同一个指针。请看我关于这个问题的帖子:很有趣,谢谢@TomLokhorst!这里最好猜测静态常数,因为它们是线程safe@yuchen-这能回答问题吗?我知道这可能会有帮助,但仍然没有更多的方法来获取当前队列。@Klaas Getting AFAIK,“获取当前队列对象”是被禁止的,也是一种强烈反对的做法。我认为有几个潜在的意图…我知道,但OP要求这样做。是否有任何理由不将其用于调试目的?(我知道)
var label: String { get } 
macOS 10.10+