[笔记] 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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容