

CoreLocationを使って、iphone ios13
swift5.2でフォア、バックグラウンド、アプリ終了時にユーザの位置情報をUserDefaultに保存したいです。  
フォア、バックグラウンドは出来そうなのですが、アプリ終了してから位置情報取得する方法がわかりません。

Background Models> Location Update にはチェック入れました。それ以外に必要なことはあるのでしょうか。  
authorizationStatus は「常に許可」の状態です。  
意外に検索しても出てこなかったため途方に暮れてます。

よろしくお願いいたします。


CC BY-SA 4.0
2020-07-09T08:36:09.173
68432
2022-07-16T04:04:55.533
2020-07-09T13:01:29.773
3060
41017
question
swift ios iphone swift5
アプリ終了しても位置情報取得したい


Appleの公式サイトに次のようなドキュメントがあります。

[Handling Location Events in the
Background](https://developer.apple.com/documentation/corelocation/getting_the_user_s_location/handling_location_events_in_the_background)

必要な設定等は、再度じっくりチェックしてもらう(Info.plistの設定のことが同ページには見当たりませんが、これはiOS
13での変更点も含めて、日本語の良記事が見つかると思います)として、見ていただきたいのは表1([Table-1](https://developer.apple.com/documentation/corelocation/getting_the_user_s_location/handling_location_events_in_the_background#2865362))です。

その中で **Launches app**
と言うのが、「(停止中の)アプリを起動してくれる」と言う意味になります。その欄に`Yes`が付いているのは、以下の3つのサービスのみです。

  * Significant-change location service
  * Visits service
  * Region monitoring

あなたの言う「位置情報取得」は、おそらく通常の位置情報サービス(Standard location service)だと思うのですが、その行は
**Launches app** が`No`になっているのがわかると思います。

つまり、通常の位置情報サービスを使用する限り、

**何をどう設定しても、アプリの停止中に位置情報を取得することはできません。**

* * *

(Visits serviceとRegion monitoringは通常の位置情報サービスとは大きくかけ離れているので)Significant-change
location serviceの仕様があなたのアプリの目的に合うならば、そちらを使用するように書き換える。

それが使えそうもないならば、「そんなことはできない」と言うことを前提にアプリの機能を見直すことが必要だろうと思います。

* * *

なお、私のやり方が悪かっただけかもしれませんが、Significant-change location
serviceをかなり前に試した時は、「うまく位置情報を拾えればラッキー」程度の精度でしか情報を拾えませんでした。実アプリに適用する前に、使い物になるかどうか、検証用のコードを作って実機で試してみることをお勧めします。


CC BY-SA 4.0
2020-07-09T11:52:05.107
68441
2020-07-09T11:52:05.107
13972
68432
answer


ありがとうございます。Handling Location Events in the Background参考になりました。  
以下の内容が、サイトの情報もとにコーディングした内容です。  
`willFinishLaunchingWithOptions` でlaunchOptionsを取得して、キーで  
UIApplication.LaunchOptionsKey がセットされていたら、
osから終了してるアプリをコールされてる状態なので、オブジェクトを再生成。Significant-change location
serviceに切り替えます。  
通常時はstartUpdatingLocationを呼んで、standardで実行してます。  
一応実機で試してみたら、フォア、バックグランドは大丈夫ですが、TERMINATEDの状態だとよくわかりませんでした。移動距離が数百メートだったからか取得できてる位置情報がなかったです。  
「startUpdatingLocationを呼んで、standardで実行」切り替えるときに、locationManagerは生成しなおしたほうがいいのか、また生成するときに呼ぶメソッドごちにパラメータが違うのかわかりませんでした。

[code]

    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
            if  let _ = launchOptions?[UIApplication.LaunchOptionsKey.location] {
                generateManager()
                locationManager?.stopUpdatingLocation()
                locationManager?.startMonitoringSignificantLocationChanges()
                return true
            }
            generateManager()
            locationManager?.startUpdatingLocation()
            locationManager?.stopMonitoringSignificantLocationChanges()
            return true
        }
    
        func applicationWillEnterForeground(_ application: UIApplication) {
            // アプリがフォアグラウンドへ移行するタイミングを通知
            locationManager?.startMonitoringSignificantLocationChanges()
            locationManager?.startUpdatingLocation()
    
        }
        func applicationDidEnterBackground(_ application: UIApplication) {
            locationManager?.stopUpdatingLocation()
            locationManager?.startMonitoringSignificantLocationChanges()
        }
        
    
        func generateManager() {
            locationManager = CLLocationManager()
            locationManager?.allowsBackgroundLocationUpdates = true
            locationManager?.pausesLocationUpdatesAutomatically = false
            locationManager?.desiredAccuracy = kCLLocationAccuracyBest
            locationManager?.distanceFilter = 5
            locationManager?.delegate = self
            locationManager?.requestAlwaysAuthorization()
        }
    
    }
    
    extension AppDelegate : CLLocationManagerDelegate {
        
        func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
            print("error:: \(error.localizedDescription)")
        }
        
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            if let latlon = locations.last {
                let latitude = latlon.coordinate.latitude
                let longitude = latlon.coordinate.longitude
                let model = LocationModel()
                model.lat = latitude
                model.lon = longitude
                //ここで位置情報保存
            }
        }
    }
    
[/code]


CC BY-SA 4.0
2020-07-10T04:30:44.827
68460
2020-07-10T04:30:44.827
41017
68432
answer