唤起app

iOS开发-电子围栏区域监听深入篇

2019-01-10  本文已影响50人  番茄炒西红柿啊

1.前言:

2.关于位置访问权限的问题:

3.关于CLRegion:

请使用CLRegion的子类,比如:CLCircularRegion.

4.核心代码(swift为例):

// 创建监听区域
let region = CLCircularRegion.init(center: coordinate, radius: distance, identifier: type.rawValue)
// 开始监听
self.locationManager.startMonitoring(for: region)
// 延时2秒后获取围栏状态(为什么延时,请看后文)
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
  self.locationManager.requestState(for: region)
}
    func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
        print("...进入电子围栏...")
    }
    
    
    func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
        print("...离开电子围栏...")
    }
    
    
    func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) {
        print("...监听围栏失败:\(region!), error:\(error)")
    }
    
    
    func locationManager(_ manager: CLLocationManager, didStartMonitoringFor region: CLRegion) {
        print("...开始监听...")
    }
    func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
        let regionType = RegionType.init(rawValue: region.identifier)
        guard regionType != .unknown else {return}
        let str = state == .inside ? "状态: 电子围栏内" : (state == .outside ? "状态: 电子围栏外" : "状态: 未知")
        if regionType == .company
        {
            self.clabel.text = str
        }
        else
        {
            self.hLabel.text = str
        }
    }

5.关于监听电子围栏数量问题:

6.关于startMonitoring方法和requestState方法的区别,以及为何要requestState延时调用问题

7.针对在始终访问权限下App被销毁后,关于移除电子围栏你需要注意的问题

实践:
1.当我没有开始监听时,获取此集合的count = 0;
2.当我开启一个电子围栏后,销毁App.然后重启App.获取此集合的count = 1
结论:
App被销毁后,下次重启App.之前没有移除的电子围栏仍然处于监听状态.不需要重新添加.
所以:这里需要特别注意,前面提到了一个App最多只能监听20个区域.因此电子围栏的监听和移除管理,自己要心里特别清晰.哪些不用了需要及时移除,否则会占用不必要的名额.另外一点就是,如果某个电子围栏不需要监听了请及时移除,否则,即使用户销毁了App,仍然还是会占用系统资源,背地里在使用用户的位置权限.作为强迫症的我可受不了.

8.最后再说一下didEnterRegion和didExitRegion这两个代理回调的执行

    func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
        print("...进入电子围栏...")
        self.locationManager.requestState(for: region)
        let type = RegionType.init(rawValue: region.identifier)!
        let str = type == .home ? "🏠" : "公司"
        self.addLocalNotification(body: "你已经进入\(str)电子围栏内")
    }
    
    
    func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
        print("...离开电子围栏...")
        self.locationManager.requestState(for: region)
        let type = RegionType.init(rawValue: region.identifier)!
        let str = type == .home ? "🏠" : "公司"
        self.addLocalNotification(body: "你已经离开\(str)电子围栏")
    }

代码思路很简单,我把注册本地通知的代码写在了代理回调里.如果回调执行了,那么本地通知就能注册成功,我就能收到通知.如果不执行,本地通知就不会被注册,我就收不到通知.最后结果如图:


0927B894-6F6A-4D3D-A22F-25E0D8A8ABB4.png

9.写在最后

在验证上文那些内容的时候,我顺带写了一个小项目,demo里弄了2个电子围栏,一个是公司的一个是租房的.每天上下班可以监听我是否到公司了,是否到家了.无论是离开还是进入电子围栏都会给我发个本地通知.然后就是当时Domain=kCLErrorDomain Code=5这个问题困住了我许久.解决的时候参考了以下文章(其实没帮到我什么,但是code=5的原因很多,如果你也遇到了,也许这里会有你想要的):

最后附上demo地址:github

上一篇下一篇

猜你喜欢

热点阅读