【iOS】7.4 定位服務->2.1.3.3 定位 - 官方框架CoreLocation 功能3:區域監聽

本文並不是最終版本,若是想要關注更新或更正的內容請關注文集,聯繫方式詳見文末,若有疏忽和遺漏,歡迎指正。ios


本文相關目錄:
================== 所屬文集:【iOS】07 設備工具 ==================
7.4 定位服務->1.0 簡介
7.4 定位服務->2.1.1 定位 - 官方框架CoreLocation: 請求用戶受權
7.4 定位服務->2.1.2 定位 - 官方框架CoreLocation: CLLocationManager位置管理器
7.4 定位服務->2.1.3.1 定位 - 官方框架CoreLocation 功能1:地理定位
7.4 定位服務->2.1.3.2 定位 - 官方框架CoreLocation 功能2:地理編碼和反地理編碼
7.4 定位服務->2.1.3.3 定位 - 官方框架CoreLocation 功能3:區域監聽
7.4 定位服務->2.1.4 定位 - 官方框架CoreLocation 案例:指南針效果
7.4 定位服務->2.2 定位 - locationManager框架
7.4 定位服務->3.1 地圖框架MapKit 功能1:地圖展現
7.4 定位服務->3.2 地圖框架MapKit 功能2:路線規劃(導航)
7.4 定位服務->3.3 地圖框架MapKit 功能3:3D視圖
7.4 定位服務->3.4 地圖框架MapKit 功能4:地圖截圖
7.4 定位服務->3.5 地圖框架MapKit 功能5:POI檢索
================== 所屬文集:【iOS】07 設備工具 ==================git


定位目錄:

官方框架CoreLocation目錄:

定位的功能實現:

本文目錄:


1.0 概念解釋


2.0 監聽思路


3.0 問題:區域監聽, 測試沒有效果?


代碼7:區域監聽 Demo

編譯環境:Xcode 8.0
模擬器版本:iOS 10
Swift版本:3.0github

【OC 語言】
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>

@interface ViewController () <CLLocationManagerDelegate>
@property(nonatomic, strong) CLLocationManager *locationM;
@end

@implementation ViewController

#pragma mark - 懶加載
- (CLLocationManager *)locationM {
    if (!_locationM) {
        // 建立CLLocationManager對象並設置代理
        _locationM = [[CLLocationManager alloc] init];
        _locationM.delegate = self;
        
        // 請求先後臺定位, 或前臺定位受權, 並在Info.Plist文件中配置相應的Key
        if ([_locationM respondsToSelector:@selector(requestAlwaysAuthorization)]) {
            [_locationM requestAlwaysAuthorization];
        }
    }
    return _locationM;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    if([CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]])
    {
    
    // 0.判斷區域監聽服務是否可用(定位服務是否關閉, 定位是否受權,是否開啓飛行模式)
        if ([CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]]) {
      
        // 1.建立區域中心
        CLLocationCoordinate2D center = CLLocationCoordinate2DMake(21.123, 124.345);
        // 指定區域半徑
        CLLocationDistance radius = 100;
        
        // 區域半徑若是大於最大區域監聽半徑,則沒法監聽成功
        if (radius > self.locationM.maximumRegionMonitoringDistance) {
            radius = self.locationM.maximumRegionMonitoringDistance;
        }
        
        // 根據區域中心和區域半徑建立一個區域
        CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:center
                                                                     radius:radius
                                                                 identifier:@"TD"];
        
        // 2. 開始監聽指定區域 (這個方法, 只會當進入或者離開區域這個動做觸發時, 纔會調用對應的代理方法)
        [self.locationM startMonitoringForRegion:region];
        
        // 請求獲取某個區域的當前狀態
        [self.locationM requestStateForRegion:region];
    } else {
        NSLog(@"區域監聽不可用");
    }
 }
}

#pragma mark - CLLocationManagerDelegate
#pragma mark - 進入監聽區域後調用(調用一次)
- (void)locationManager:(nonnull CLLocationManager *)manager didEnterRegion:(nonnull CLRegion *)region {
    
    NSLog(@"進入區域---%@", region.identifier);
}

#pragma mark - 進入監聽區域後調用(調用一次)
- (void)locationManager:(nonnull CLLocationManager *)manager didExitRegion:(nonnull CLRegion *)region {
    
    NSLog(@"離開區域---%@", region.identifier);
}

#pragma mark - 當監聽區域失敗時調用
// 監聽區域個數是有上限的,若是大於上限,再註冊區域就會失敗,就會執行此方法)
- (void)locationManager:(nonnull CLLocationManager *)manager
monitoringDidFailForRegion:(nullable CLRegion *)region
              withError:(nonnull NSError *)error {
    
    // 經驗: 通常都是在此處把比較遠的區域給移除
//    [manager stopMonitoringForRegion:region];
}

#pragma mark - 請求某個區域狀態時, 回調的代理方法
- (void)locationManager:(CLLocationManager *)manager
      didDetermineState:(CLRegionState)state
              forRegion:(CLRegion *)region {
    
    switch (state) {
        case CLRegionStateUnknown:
            NSLog(@"未知狀態");
            break;
        case CLRegionStateInside:
            NSLog(@"在區域內部");
            break;
        case CLRegionStateOutside:
            NSLog(@"在區域外部");
            break;
        default:
            break;
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

打印結果:swift

OC - 區域監聽[12621:389819] 在區域內部

OC - 區域監聽[12621:389819] 離開區域---TD
OC - 區域監聽[12621:389819] 在區域外部

OC - 區域監聽[12621:389819] 進入區域---TD
OC - 區域監聽[12621:389819] 在區域內部

【Swift語言】微信

import UIKit
import CoreLocation

class ViewController: UIViewController {
    
    @IBOutlet weak var Label: UILabel!
    
    lazy var locationM: CLLocationManager = {
        
        let locationM = CLLocationManager()
        locationM.delegate = self
        
        // 請求受權 配置key
        if #available(iOS 8.0, *) {
            locationM.requestAlwaysAuthorization()
        }
        return locationM
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 若是想要進行區域監聽, 在ios8.0以後, 必需要請求用戶的位置受權
        
        // 0. 先判斷區域監聽是否可用
        if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self){
        
        // 1. 建立區域中心
        let center = CLLocationCoordinate2DMake(21.123, 124.345)
        var distance: CLLocationDistance = 10
        
        // 區域半徑若是大於最大區域監聽半徑,則沒法監聽成功
        if distance > locationM.maximumRegionMonitoringDistance {
            distance = locationM.maximumRegionMonitoringDistance
        }
        
        // 根據區域中心和區域半徑建立一個區域
        let region  = CLCircularRegion(center: center, radius: distance, identifier: "TD")
        
        // 2. 開始監聽指定區域 (這個方法, 只會當進入或者離開區域這個動做觸發時, 纔會調用對應的代理方法)
        locationM.startMonitoring(for: region)
        
        // 請求獲取某個區域的當前狀態
        locationM.requestState(for: region)
        
        }else{
            print("區域監聽不可用")
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

extension ViewController: CLLocationManagerDelegate {
    
    // 進入區域時調用
    func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
        print("進入區域--" + region.identifier)
        Label.text = "進入區域"
    }
    
    // 離開區域時調用
    func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
        print("離開區域--" + region.identifier)
        Label.text = "離開區域"
    }
    
    // 當請求某個區域狀態時, 若是獲取到對應狀態就會調用這個方法
    func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
        
        if region.identifier == "TD" {
            if state == CLRegionState.inside{
                Label.text = "您已進入---" + region.identifier + "區域"
            }else if state == CLRegionState.outside {
                Label.text = "您已離開---" + region.identifier + " 區域"
            }else {
                Label.text = "其餘"
            }
        }
    }    
}

打印結果:框架

進入區域--TD
離開區域--TD


本文源碼 Demo 詳見 Github
https://github.com/shorfng/iOS_7.0_Device-Toolside


做者:藍田(Loto)
【做品發佈平臺】

簡書
博客園
Gitbook(若是以爲文章太長,請閱讀此平臺發佈的文章)工具

【代碼託管平臺】

Github測試

【若有疑問,請經過如下方式交流】

評論區回覆
發送郵件shorfng@126.com網站


本文版權歸做者和本網站共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,謝謝合做。


若是以爲個人文章對您有用,請隨意打賞。您的支持將鼓勵我繼續創做!
  • 支付寶掃一掃 向我打賞

  • 你也能夠微信 向我打賞

相關文章
相關標籤/搜索