[笔记] Swift-ibeacon微定位打卡开发

ibeacon是基于地理位置的微定位技术,区别于BLE。
两者无任何关系。ibeacon使用CoreLocation库,而BLE使用CoreBluetooth库。

开发ibeacon需要了解beacon三个标识:

UUID:用来标记某一类beacon
major:主要值,用于区别子类
minor:次要值,用于区别子类类下一级

如果开发打卡功能。则一般蓝牙硬件都使用同一个UUID,用于匹配此类beacon,使用major和minor来区别不同教室。

使用之前需倒入:
import CoreLocation

同时info.plist文件添加定位权限:
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
NSLocationAlwaysAndWhenInUseUsageDescription

创建IbeaconManager类
直接上代码:

import UIKit
import CoreLocation

//蓝牙开启通知
// did centralManager enable notification
let BluetoothNotificationManagerEnable = "BabyNotificationAtCentralManagerEnable"

// 蓝牙弹框是需要弹出
let BluetoothAlertIsShow = "BluetoothAlertIsShow"

// 搜索到设备数组
typealias IbeaconSearchResults = (([CLBeacon]) -> ())

class IbeaconManager: NSObject {

    static let `default` = IbeaconManager()
    
    var searchResultsCallback: IbeaconSearchResults?
    
    fileprivate var beaconSendRegion: CLBeaconRegion! // 发送
    fileprivate var beaconReceiveRegion: CLBeaconRegion! // 接受
    fileprivate var locationManager: CLLocationManager!
    fileprivate var beaconPeripheralData: NSDictionary!
    fileprivate var peripheraManager: CBPeripheralManager!
    var location: Float = 0.0 //距离
    let beaconIdentifier = "ibeaconTest"
    let defaultUUIDString = "XXXX-XXXXXX-XXXXXX-XXXXXXXXXX"
    
    override init() {
        super.init()
        
        // 发射信号
        // 此处代码用另一部手机运行 模拟ibeacon设备发送信号
        beaconSendRegion = CLBeaconRegion(proximityUUID: UUID(uuidString: defaultUUIDString)!, major: 1234, minor: 5678, identifier: beaconIdentifier)
        beaconPeripheralData = beaconSendRegion.peripheralData(withMeasuredPower: nil)
        peripheraManager = CBPeripheralManager(delegate: self, queue: nil)
        

        // 接受信号
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.requestAlwaysAuthorization()
        beaconReceiveRegion = CLBeaconRegion(proximityUUID: UUID(uuidString: defaultUUIDString)!, identifier: beaconIdentifier)
        beaconReceiveRegion.notifyEntryStateOnDisplay = true
        
        //请求一直允许定位
        locationManager.requestAlwaysAuthorization()
        beaconReceiveRegion.notifyEntryStateOnDisplay = true
    }
    
    /// 开始扫描
    func startRunningBeacons() {
        //开始扫描
        locationManager.startMonitoring(for: beaconReceiveRegion)
        locationManager.startRangingBeacons(in: beaconReceiveRegion)
    }
    
}

extension IbeaconManager: CLLocationManagerDelegate {
    
    //进入beacon区域
    func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
        locationManager.startRangingBeacons(in: beaconReceiveRegion)
        print( "进入beacon区域")
    }
    
    //离开beacon区域
    func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
        locationManager.stopRangingBeacons(in: beaconReceiveRegion)
        print("离开beacon区域")
    }
    
    func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {
        //返回是扫描到的beacon设备数组,这里取第一个设备
        guard beacons.count > 0 else { return }
        
        self.searchResultsCallback?(beacons)
        
        // 下面为调试信息
        let beacon = beacons.first!
        print("major====",beacon.major)
        print("minor====",beacon.minor)
        //accuracy可以获取到当前距离beacon设备距离
        let location = String(format: "%.3f", beacon.accuracy)
        print( "距离第一个beacon\(location)m")
    }
    
    func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) {
        print("Failed monitoring region: \(error.localizedDescription)")
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("Location manager failed: \(error.localizedDescription)")
    }
}

extension IbeaconManager: CBPeripheralManagerDelegate {
    
    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        
        switch peripheral.state {
        case .poweredOn:
            peripheraManager.startAdvertising(beaconPeripheralData as? [String : Any])
            print("蓝牙打开了!=============================")
            print(beaconReceiveRegion.proximityUUID)
            print(beaconReceiveRegion.major)
            print(beaconReceiveRegion.minor)
            print(beaconReceiveRegion.identifier)
            print("蓝牙打开了!=============================")
            UserDefaults.standard.set(true, forKey: BluetoothNotificationManagerEnable)
            UserDefaults.standard.synchronize()
        case .poweredOff:
            print("蓝牙未打开")
            UserDefaults.standard.set(false, forKey: BluetoothNotificationManagerEnable)
            UserDefaults.standard.synchronize()
        default: peripheraManager.stopAdvertising()
            
        }
    }
}

需要使用的地方

/// 开始搜索蓝牙列表 | 只要搜索到了就记录值 用于对比教师课程里的UUID是否跟这个一致 | 如果一致说明在蓝牙搜索的范围内 可以执行签到 如果没有则不在搜索范围内
    func startBlueToothSearch(blueToothNotOpen: (()->())?) {
        
        IbeaconManager.default.startRunningBeacons()
        IbeaconManager.default.searchResultsCallback = { (ibeacons) in
            var location = Double(1000)
            for ibeacon in ibeacons {
                let majorMinor = "\(ibeacon.major)\(ibeacon.minor)"
                // 值越小代表距离最近 ibeacon.accuracy 为距离
                if ibeacon.accuracy <= location {
                    location = ibeacon.accuracy
                }
                print("major====",ibeacon.major)
                print("minor====",ibeacon.minor)
                let location = String(format: "%.3f", ibeacon.accuracy)
                print( "距离beacon====\(location)m")
            }
        }
        
        // 检测蓝牙是否打开
        if let enable = UserDefaults.standard.value(forKey: BluetoothNotificationManagerEnable) as? Bool {
            if enable == false {
                blueToothNotOpen?()
            }
        }else {
            blueToothNotOpen?()
        }
    }

Over !

参考:
https://www.jianshu.com/p/83b9f03316e8

你可能感兴趣的:([笔记] Swift-ibeacon微定位打卡开发)