2017-11-15 14 views
1

ユーザーがapp.nowを使用していなくてもユーザーの場所を取得したい場合は、ホームボタンを押してアプリケーションをバックグラウンド状態にした後に場所を取得できますが、数秒後に場所の更新を停止します。そして、私が停止してからアプリケーションの場所の更新を殺しているとき。これはアプリケーションデリゲートの私のコードです。バックグラウンドでの更新場所

let locationManager = CLLocationManager() 
    var LatitudeGPS = String() 
    var LongitudeGPS = String() 
    var speedGPS = String() 
    var Course = String() 
    var Altitude = String() 
    var bgtimer = Timer() 

func applicationDidEnterBackground(_ application: UIApplication) { 

    self.doBackgroundTask() 
    } 

    func beginBackgroundUpdateTask() { 

    backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: { 
     self.endBackgroundUpdateTask() 
    }) 

    } 

    func endBackgroundUpdateTask() { 
    UIApplication.shared.endBackgroundTask(self.backgroundUpdateTask) 
    self.backgroundUpdateTask = UIBackgroundTaskInvalid 
    } 
func doBackgroundTask() { 

    DispatchQueue.global(qos: .background).async { 

    self.beginBackgroundUpdateTask() 
    self.StartupdateLocation() 
    self.bgtimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.bgtimer(timer:)), userInfo: nil, repeats: true) 
    RunLoop.current.add(self.bgtimer, forMode: RunLoopMode.defaultRunLoopMode) 
    RunLoop.current.run() 
    self.endBackgroundUpdateTask() 

    } 


} 


func bgtimer(timer:Timer!){ 
    print("Fired from Background ************************************") 
    updateLocation() 
} 
    func StartupdateLocation() { 
    locationManager.delegate = self 
    locationManager.startUpdatingLocation() 
    locationManager.desiredAccuracy = kCLLocationAccuracyBest 
    locationManager.distanceFilter = kCLDistanceFilterNone 
    locationManager.requestAlwaysAuthorization() 
    locationManager.allowsBackgroundLocationUpdates = true 
    locationManager.pausesLocationUpdatesAutomatically = false 
    } 

    func updateLocation() { 
locationManager.startUpdatingLocation() 
    locationManager.stopUpdatingLocation() 
    print("Latitude: \(LatitudeGPS)") 
    print("Longitude: \(LongitudeGPS)") 
    print("Speed: \(speedGPS)") 
    print("Heading: \(Course)") 
    print("Altitude BG: \(Altitude)") 
    DispatchQueue.main.async { 
     print(UIApplication.shared.backgroundTimeRemaining) 

    } 
    } 

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 

    LatitudeGPS = String(format: "%.10f", manager.location!.coordinate.latitude) 
    LongitudeGPS = String(format: "%.10f", manager.location!.coordinate.longitude) 
    speedGPS = String(format: "%.3f", manager.location!.speed) 
    Altitude = String(format: "%.3f", manager.location!.altitude) 
    Course = String(format: "%.3f", manager.location!.course) 

    } 
} 

数秒私のアプリケーションが終了し、位置更新が立ち止まった後、私は思います。 20分後にアプリケーション終了(OSまたはユーザー)がバッテリの充電を維持するために場所の更新を停止したいと思っています。 場所の更新に問題があります。

答えて

2

変更するもののいくつか。

ステップ1:

enter image description here

ステップ2の下に示すように、あなたのプロジェクトの機能セクションに位置情報の更新をバックグラウンドモードを有効にしていることを確認してください

そして私がstに対するアプリの位置更新を殺しているときoped。

あなたがこのサービスを開始し、あなたのアプリがその後に終了した場合、新たな イベントが到着した場合、 システムが自動的にバックグラウンドにアプリをrelaunches

リンゴのドキュメントから引用。 willFinishLaunchingWithOptions :)と アプリケーション(:didFinishLaunchingWithOptions :)あなたのアプリのメソッド デリゲートはアプリが ための場所で開始されたことを示すためにキーの場所が含まれているような場合には、オプションが アプリケーション(に渡された辞書イベント。再起動時には、まだ ロケーションマネージャオブジェクトを設定し、このメソッドを呼び出して、 ロケーションイベントを受信し続ける必要があります。位置情報サービスを再開すると、すぐに現在のイベント が代理人に配信されます。さらに、 ロケーションマネージャオブジェクトのlocationプロパティには、 サービスを開始する前でも、最新のロケーションオブジェクトを持つ が設定されています。

リンク:https://developer.apple.com/documentation/corelocation/cllocationmanager/1423531-startmonitoringsignificantlocati

重要なことは、声明の上で注意すべきは、あなたはまだ、ロケーションマネージャオブジェクトと 呼び出し場所イベントを受信し続けるためにこの方法を設定する必要があり、リニューアルの際

です。

つまり、現在のロケーションマネージャはあまり使用されないため、新しいインスタンスマネージャを作成して新しいインスタンスを設定し、startMonitorSignificantLocationChangesを再度呼び出す必要があります。

iOSは、startMonitoringSignificantLocationChangesを使用した場合にのみ、終了したアプリに位置情報を送信します。

あなたのアプリが終了し、iOSがロケーションのアップデートを受信して​​再起動した場合にのみ適用されるすべてです。しかし、あなたのアプリが単にバックグラウンドであれば、使用する必要はありませんstartMonitorSignificantLocationChanges

startUpdatingLocationは、アプリがバックグラウンド/フォアグラウンドモードの場合にのみ機能します。アプリが停止または強制終了された場合、iOSは場所の更新を停止します。

あなたがこのサービスを開始し、アプリが中断された場合は、あなたのアプリが( の前景または背景のいずれか)を再度実行が開始されるまで、システムは、イベントの 配信を停止します。あなたのアプリが終了した場合、新しいロケーションイベントの配信 が完全に停止します。したがって、バックグラウンドで位置イベントを受信するためにアプリに が必要な場合は、 UIBackgroundModesキー(位置値付き)をInfo.plist ファイルに含める必要があります。

リンク:

https://developer.apple.com/documentation/corelocation/cllocationmanager/1423750-startupdatinglocationだからstartMonitoringSignificantLocationChangesstartupdatinglocationの適切な使用についてだったあなたのコード

locationManager.startMonitoringSignificantLocationChange() 

[OK]を変更します。今あなたのコードの間違いのためのタイマー。

間違い1:

self.bgtimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.bgtimer(timer:)), userInfo: nil, repeats: true) 

場所にタイムリーな更新プログラムを入手するためにタイマーを使います。それはどのように動作しないのですか?あなたはTimerを永遠に走らせることはできません。あなたのアプリが中断または終了するとすぐにタイマーが停止します。ロケーションマネージャーは、ロケーションが変更されたときにアプリに通知し、そのロケーションのみに依存する必要があります。タイムリーにタイマーを実行して、ロケーションのアップデートをチェックすることはできません。サスペンド状態または終了状態では実行されません。

間違い2:

func updateLocation() { 
    locationManager.startUpdatingLocation() 
    locationManager.stopUpdatingLocation() 

なぜ開始し、その後の文でアップデート場所を停止しますか?それはあまり意味がありません。

間違い3:

func StartupdateLocation() { 
    locationManager.delegate = self 
    locationManager.startUpdatingLocation() 

あなたStartupdateLocationは、複数の時間と呼ばれ、すべての時間があなたには、繰り返しロケーションマネージャの同じインスタンス上startUpdatingLocationを呼び出している、このメソッドを呼び出します。あなたはそれをする必要はありません! startUpdatingLocationまたはstartMonitoringSignificantLocationChangeには1回しか電話できません。

+1

func locationManager(_ manager:CLLocationManager、didUpdateLocations locations:[CLLocation])で、更新位置を呼び出す必要があります。 – ava

+0

location manager.startMonitoringSignificantLocationChanges()の1つのインスタンスに対してこのtowメソッドを追加できます。 locationManager.startUpdatingLocation() – ava

+0

@ava:Bingo buddyあなたはlocationManagerの場所を更新する必要があります –

関連する問題