使getNotificationSettings返回而不是使用完成块

And*_*res 3 semaphore apple-push-notifications ios swift

我有一种正在使用的应用程序的多个位置使用的方法。这是一种检查是否启用了远程推送通知的方法。该方法返回一个值,但是您可能已经知道该方法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
}
Run Code Online (Sandbox Code Playgroud)

编辑:

我关注了@rmaddy的评论,至少现在它没有崩溃,但被卡在了wait()。如果我转到调试器并e semasphore.signal()完成,并且应用程序继续正常运行。不知何故,没有调用完成块。

rma*_*ddy 6

在这种情况下,您需要创建一个初始值为而0不是的信号量2

let semasphore = DispatchSemaphore(value: 0)
Run Code Online (Sandbox Code Playgroud)

在文档中提到了这一点:

当两个线程需要协调特定事件的完成时,将值传递为零非常有用。

wait首先递减值。然后,它将阻塞,直到该值大于或等于0。将值减小为1,并且将其减小为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
}
Run Code Online (Sandbox Code Playgroud)