iOS 13 - 如何检查用户是否接受了蓝牙权限?

iOS 13 - How to check if user has accepted Bluetooth permission?

作为 iOS 13 的一部分,应用现在需要请求权限才能访问蓝牙。

如何检查用户是否接受了蓝牙权限?

CBCentralManager extends CBManager. As of iOS 13, CBManager has an authorization 属性.

使用此 属性 确定权限是未知、允许、拒绝还是受限。

需要说明的是,在iOS下,需要使用实例属性authorization,而不是同名类型属性。确保在 CBCentralManager.

的实例上访问 authorization

Swift 5 IOS 13基于已接受的答案,但处理外设连接类型:

    enum BluetoothConnectionType {
        case central, peripheral
    }

    func isBluetoothAuthorized(forType type: BluetoothConnectionType) -> Bool {
        switch type {
        case .central:
            if #available(iOS 13.1, *) { return CBCentralManager.authorization == .allowedAlways }
            if #available(iOS 13.0, *) { return CBCentralManager().authorization == .allowedAlways }
            return true
        case .peripheral:
            if #available(iOS 13.1, *) { return CBPeripheralManager.authorization == .allowedAlways }
            if #available(iOS 13.0, *) { return CBPeripheralManager.authorizationStatus() == .authorized }
            return true
        }
    }

有趣的是,启动iOS 13.1可以在不分配CBManager的情况下检查BT权限。这是一个巨大的优势,因为初始化 CBManager 将自动触发系统弹出窗口,以防 BT 权限之前不是 asked/given。

func checkPermission() -> CBManagerAuthorization {
    if #available(iOS 13.1, *) {
        return checkPermissionBeforeCBManagerAllocation()
    } else {
        return checkPermissionLegacy()
    }
}

@available(iOS 13.1, *)
private func checkPermissionBeforeCBManagerAllocation() -> CBManagerAuthorization {
    CBCentralManager.authorization
}

private func checkPermissionLegacy() -> CBManagerAuthorization {
    let manager = CBCentralManager(delegate: self, queue: nil)
    return manager.authorization
}

以上只是 iOS 13.x 版本的示例,不处理低于该版本的任何内容。

试试这个:

var isBluetoothPermissionGranted: Bool {
    if #available(iOS 13.1, *) {
        return CBCentralManager.authorization == .allowedAlways
    } else if #available(iOS 13.0, *) {
        return CBCentralManager().authorization == .allowedAlways
    }
    
    // Before iOS 13, Bluetooth permissions are not required
    return true
}

这是我要使用的(针对所有 iOS 的完整解决方案):Swift 5

class MainViewController: UIViewController {
    var isiOSBluetoothOn = false
       
    @IBAction func onBluetoothButtonClicked(_ sender: Any){
        if (isiOSBluetoothOn) {
            let newVC = self.storyboard?.instantiateViewController(withIdentifier: "blevc")
            self.navigationController?.pushViewController(newVC!, animated: true)
        } else {
            if #available(iOS 13.0, *) {
                if (CBCentralManager().authorization != .allowedAlways) {   //System will automatically ask user to turn on iOS system Bluetooth if this returns false
                   openAppOrSystemSettingsAlert(title: "Bluetooth permission is currently disabled for the application. Enable Bluetooth from the application settings.", message: "")
                }
            } else {
                let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String
                openAppOrSystemSettingsAlert(title: "\"\(appName ?? "You Application Nam")\" would like to use Bluetooth for new connections", message: "You can allow new connections in Settings")
            }
        }
    }
                
    func openAppOrSystemSettingsAlert(title: String, message: String) {
        let alertController = UIAlertController (title: title, message: message, preferredStyle: .alert)
        let settingsAction = UIAlertAction(title: "Settings", style: .default) { (_) -> Void in
            guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else { return }
            if UIApplication.shared.canOpenURL(settingsUrl) {
                UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                    print("Settings opened: \(success)") // Prints true
                })
            }
        }
        alertController.addAction(settingsAction)
        let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
        alertController.addAction(cancelAction)
        present(alertController, animated: true, completion: nil)
    }
}

extension MainViewController: CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .poweredOn:
           isiOSBluetoothOn = true
            break
        case .poweredOff:
           isiOSBluetoothOn = false
            break
        default:
            break
        }
    }
}