ある地点への接近を知らせる(CoreLocation::CLLocationManager.startMonitoringForRegion)

  • 0
    いいね
  • 0
    コメント
    この記事は最終更新日から1年以上が経過しています。

    地理的領域の観測

    LocationManager準備

    Info.plistのRequired device capabilitiesにlocation-services追加
    Info.plistのInformation Property ListにNSLocationAlwaysUsageDescriptionを追加して、許可を求めるダイアログに表示する文字列を設定

    ViewController.swift
    import UIKit
    import CoreLocation
    
    class ViewController: UIViewController, CLLocationManagerDelegate {
    
        var myLocationManager: CLLocationManager!
    

    領域観測許可取得

    ViewController.swift
            super.viewDidLoad()
    
            if !CLLocationManager.isMonitoringAvailableForClass(CLCircularRegion) {
                return
            }
    
            let status = CLLocationManager.authorizationStatus()
            if status == CLAuthorizationStatus.Restricted || status == CLAuthorizationStatus.Denied {
                return
            }
    
            myLocationManager = CLLocationManager()
            myLocationManager.delegate = self
    
            if status == CLAuthorizationStatus.NotDetermined {
                myLocationManager.requestAlwaysAuthorization()
            }
    
            if !CLLocationManager.locationServicesEnabled() {
                return
            }
    

    バックグラウンド処理実行許可確認

    Info.plistのInformation background modesにRequired background modesを追加
    画面左のファイル一覧からプロジェクト(一番上のルート)を選択し、Capabilitiesタブ->Background ModesのLocation updatesをチェック

    ViewController.swift
            if status == CLAuthorizationStatus.Restricted || status == CLAuthorizationStatus.Denied {
                return
            }
    
            if UIApplication.sharedApplication().backgroundRefreshStatus != UIBackgroundRefreshStatus.Available {
                return
            }
    

    アプリケーションが実行していないときに、ある領域の境界線を横切ると、アプリケーションはそのイベントを処理するためにバックグラウンドで起動されます。同様に、イベントが発生したときにアプリケーションが一時停止中の場合、アプリケーションは動作させられて、イベントを処理するために短い時間(約10秒)が割り当てられます。必要であればアプリケーションは、UIApplicationクラスのbeginBackgroundTaskWithExpirationHandler:メソッドを使用して、より長いバックグラウンド実行時間を要求することができます。

    地理的領域の作成・登録(iOS7.0~)

    ViewController.swift
            if UIApplication.sharedApplication().backgroundRefreshStatus != UIBackgroundRefreshStatus.Available {
                return
            }
    
            let center = CLLocationCoordinate2DMake(35.0, 139.0)
            var radius = 3000000.0
            if radius > myLocationManager.maximumRegionMonitoringDistance {
                radius = myLocationManager.maximumRegionMonitoringDistance
            }
            let identifier = "YourUniqueIdentifier"
            let geoRegion = CLCircularRegion.init(center: center, radius: radius, identifier: identifier)
            geoRegion.notifyOnEntry = true
            geoRegion.notifyOnExit = true
            myLocationManager.startMonitoringForRegion(geoRegion)
    
            myLocationManager.requestStateForRegion(geoRegion)
    
        }
    
        func locationManager(manager: CLLocationManager, didDetermineState state: CLRegionState, forRegion region: CLRegion) {
            if state == CLRegionState.Inside {
                print("inside")
            } else {
                print("outside")
            }
        }
    
        func locationManager(manager: CLLocationManager, monitoringDidFailForRegion region: CLRegion?, withError error: NSError) {
            print("fail to monitor for region")
        }
    

    地理的領域の観測は、登録後すぐに開始されるが、イベントが生成されるのは、境界を横断したときだけ
    領域の境界線を横断しないと、イベントが生成されてデリゲートに送信されない
    ユーザが領域境界内にいるかどうか判断するには、CLLocationManagerクラスのrequestStateForRegion:メソッドを使う

    領域は共有のシステムリソースであり、システム全体で利用可能な領域の総数は限られているので、Core Locationは、1つのアプリケーションで同時に観測できる領域の数を20に制限している
    ユーザの位置が変わるにつれて、距離の遠くなった領域を削除し、ユーザの進路上で近づいている領域を追加し、ユーザの近隣の領域のみ登録する
    領域を登録しようとしたときに空きがないと、位置情報マネージャはデリゲートのlocationManager:monitoringDidFailForRegion:withError:メソッドを呼び出して、エラーコードkCLErrorRegionMonitoringFailureを渡す

    境界横断イベントの処理

    ViewController.swift
                print("outside")
            }
        }
    
        func locationManager(manager: CLLocationManager, didEnterRegion region: CLRegion) {
            print("enter")
        }
    
        func locationManager(manager: CLLocationManager, didExitRegion region: CLRegion) {
            print("exit")
        }
    

    システムは、ユーザが境界線付近を移動しているときに大量のイベントを立て続けに生成するのを防ぐため、システムで定義された緩衝距離を越えるまでは境界線の横断を報告しない

    Simulatorで実行する場合は、XcodeのProduct->Scheme->Edit Scheme->Options->Default Locationで位置情報の初期値を設定しておくと良い

    参考

    位置情報とマッププログラミングガイド
    CLLocationManager Class Reference