如何解决如何检测是否在iOS 14中授予了本地网络权限
如何检测用户是否已在iOS 14应用程序中授予了本地网络权限?如果用户拒绝了权限并重定向到os设置以授予权限,则必须显示错误屏幕。 Apple是否提供了任何类似位置许可的查找方法?
解决方法
您可以使用不满意的原因属性:
connection.stateUpdateHandler = { latestState in
switch connection.state {
case .waiting(_):
if case .localNetworkDenied? = connection.currentPath?.unsatisfiedReason {
… no local network access …
}
… other states …
}
}
为要与之通信的本地网络地址创建一个NWConnection
。如果连接通过,则说明您具有本地网络访问权限。如果连接停滞在.waiting(_:)
状态,则可以查看当前路径以查看其是否正在等待本地网络访问。发件人:apple's dev forums
我编写了这个类,如果你不是在 iOS 14.2 上也可以使用。
- 该类将提示用户授予访问本地网络的权限(第一次)。
- 如果已被拒绝/授予,请验证现有权限状态。
记住这个实例必须保持活动状态,所以如果你在另一个类的函数调用中使用它,你需要在调用函数的范围之外保持实例活动。
import UIKit
import Network
class LocalNetworkPermissionChecker {
private var host: String
private var port: UInt16
private var checkPermissionStatus: DispatchWorkItem?
private lazy var detectDeclineTimer: Timer? = Timer.scheduledTimer(
withTimeInterval: .zero,repeats: false,block: { [weak self] _ in
guard let checkPermissionStatus = self?.checkPermissionStatus else { return }
DispatchQueue.main.asyncAfter(deadline: .now(),execute: checkPermissionStatus)
})
init(host: String,port: UInt16,granted: @escaping () -> Void,failure: @escaping (Error?) -> Void) {
self.host = host
self.port = port
NotificationCenter.default.addObserver(
self,selector: #selector(applicationIsInBackground),name: UIApplication.willResignActiveNotification,object: nil)
NotificationCenter.default.addObserver(
self,selector: #selector(applicationIsInForeground),name: UIApplication.didBecomeActiveNotification,object: nil)
actionRequestNetworkPermissions(granted: granted,failure: failure)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
/// Creating a network connection prompts the user for permission to access the local network. We do not have the need to actually send anything over the connection.
/// - Note: The user will only be prompted once for permission to access the local network. The first time they do this the app will be placed in the background while
/// the user is being prompted. We check for this to occur. If it does we invalidate our timer and allow the user to make a selection. When the app returns to the foreground
/// verify what they selected. If this is not the first time they are on this screen,the timer will not be invalidated and we will check the dispatchWorkItem block to see what
/// their selection was previously.
/// - Parameters:
/// - granted: Informs application that user has provided us with local network permission.
/// - failure: Something went awry.
private func actionRequestNetworkPermissions(granted: @escaping () -> Void,failure: @escaping (Error?) -> Void) {
guard let port = NWEndpoint.Port(rawValue: port) else { return }
let connection = NWConnection(host: NWEndpoint.Host(host),port: port,using: .udp)
connection.start(queue: .main)
checkPermissionStatus = DispatchWorkItem(block: { [weak self] in
if connection.state == .ready {
self?.detectDeclineTimer?.invalidate()
granted()
} else {
failure(nil)
}
})
detectDeclineTimer?.fireDate = Date() + 1
}
/// Permission prompt will throw the application in to the background and invalidate the timer.
@objc private func applicationIsInBackground() {
detectDeclineTimer?.invalidate()
}
/// - Important: DispatchWorkItem must be called after 1sec otherwise we are calling before the user state is updated.
@objc private func applicationIsInForeground() {
guard let checkPermissionStatus = checkPermissionStatus else { return }
DispatchQueue.main.asyncAfter(deadline: .now() + 1,execute: checkPermissionStatus)
}
}
//Can be used like this:
LocalNetworkPermissionChecker(host: "255.255.255.255",port: 4567,granted: {
//Perform some action here...
},failure: { error in
if let error = error {
print("Failed with error: \(error.localizedDescription)")
}
})
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。