【问题标题】:How to check local network permission in iOS 14?如何在 iOS 14 中检查本地网络权限?
【发布时间】:2021-05-03 06:43:28
【问题描述】:

我想知道如何验证用户是否允许我的应用程序访问本地网络。经过一番试验,我想出了这个解决方案。

我写了这个类,如果你不在 iOS 14.2 上也可以使用。

  1. 此类将提示用户访问本地网络的权限 (第一次)。
  2. 验证现有权限状态是否已被拒绝/授予。

请记住,这个实例必须保持活动状态,所以如果你在另一个类的函数调用中使用 this,你需要在调用函数的范围之外保持实例活动。在某些情况下,您还需要网络多播权限。

【问题讨论】:

标签: ios swift ios14 local-network ios-permissions


【解决方案1】:
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)
    }
}

在函数范围之外声明以保持活动状态。如果整个调用类稍后没有被释放以取消订阅通知,请记住在完成后设置为 nil。

可以这样使用:

class RandomClass {
    var networkPermissionChecker: LocalNetworkPermissionChecker?
    
    func checkPermissions() {
        networkPermissionChecker = 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)")
            }
        })
    }
}

【讨论】:

  • 它总是失败并显示一条消息:[C32 255.255.255.255:4567 udp, indefinite, path unsatisfied (Path was denied by NECP policy), interface: en0, ipv4, dns],即使它有 LNA 权限。
猜你喜欢
  • 2021-01-12
  • 1970-01-01
  • 2022-09-30
  • 2021-01-13
  • 2021-01-26
  • 2023-03-31
  • 1970-01-01
  • 2020-12-26
  • 1970-01-01
相关资源
最近更新 更多