我有一种方法正在我正在开发的应用程序的多个位置使用。这是一种检查是否启用了远程推送通知的方法。该方法返回一个值,但是您可能知道currentUserNotificationSettings
已被弃用,所以现在我正在使用getNotificationSettings
。
问题是第一个返回一个值,而最新的返回一个块。我希望仍然能够返回一个值以避免重构所有内容,因此我编写了以下内容,但失败了,我不明白为什么...
可以吗?!
public static var isRemoteEnabled: Bool {
var notificationSettings: UNNotificationSettings?
let semasphore = DispatchSemaphore(value: 2)
UNUserNotificationCenter.current().getNotificationSettings { setttings in
notificationSettings = setttings
semasphore.signal()
}
semasphore.wait()
guard let authorizationStatus = notificationSettings?.authorizationStatus else { return false }
return authorizationStatus == .authorized
}
已编辑:
我关注了@rmaddy注释,至少现在它没有崩溃,但被卡在wait()
中。如果我转到调试器并e semasphore.signal()
完成,则该应用程序将继续正常运行。不知何故,没有调用完成模块。
答案 0 :(得分:5)
在这种情况下,您希望创建的信号量的初始值为0
,而不是2
。
let semasphore = DispatchSemaphore(value: 0)
文档中提到了这一点:
当两个线程需要协调特定事件的完成时,将值传递为零非常有用。
wait
首先减小值。然后它将阻塞,直到该值大于或等于0。使用2时,它将减小为1,并且由于该值已经大于或等于0,因此wait
不需要阻塞,并且您的方法在致电signal
之前很久就返回了。
还有一种可能性,getNotificationSettings
的完成块可以在同一线程上调用(导致死锁),因此可以在后台队列中调用它。
public static var isRemoteEnabled: Bool {
var notificationSettings: UNNotificationSettings?
let semasphore = DispatchSemaphore(value: 0)
DispatchQueue.global().async {
UNUserNotificationCenter.current().getNotificationSettings { setttings in
notificationSettings = setttings
semasphore.signal()
}
}
semasphore.wait()
guard let authorizationStatus = notificationSettings?.authorizationStatus else { return false }
return authorizationStatus == .authorized
}