[Swift] 위치 정보를 가져오는 Timer 처리를 백그라운드에서 순환시킵니다.

11529 단어 SwiftiOS
회사가 새로운 응용 프로그램 (기존 서비스의 업데이트판) 을 개발하고 있지만, 낡은 응용 프로그램에도 설치된'백그라운드에서 위치 정보를 얻는다'는 처리는 어쨌든 순조롭지 않다. 백그라운드로 옮기면 Timer의 처리가 중단된다.
그 연관된 꼬마 콩은 오래된 앱처럼 설정도 하고 코드도 썼는데 왜일까... 하루 종일 고민했지만 아주 간단한 일이라 미니 샘플로 남겼어요.

개발 환경


터미널: MacBook Pro/MacOS10.14.5(Mojave)
Xcode:10.2.1
Swift:5

한 일


· Timer를 사용하여 백그라운드 순환 위치 정보 얻기

실시


화면 이미지
화면 중앙에 순환 처리 횟수만 표시하면 됩니다.

원본
우선 배경 모드Location updates를 열고 선택하는 것을 잊지 마십시오.

ViewController.swift

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    var myLocationManager: CLLocationManager!

    var myTimer: Timer!

    var lblTimerCount: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        // ループ処理の回数を表示するラベル
        lblTimerCount = UILabel()
        view.addSubview(lblTimerCount)
        lblTimerCount.frame = CGRect.init(x: 0, y: 0, width: 100, height: 50)
        lblTimerCount.text = String(0)
        lblTimerCount.textAlignment = .center
        lblTimerCount.center = view.center

        // 位置情報取得の設定
        myLocationManager = CLLocationManager()
        myLocationManager.delegate = self
        myLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
        myLocationManager.distanceFilter = 50

        // バックグラウンドでの位置情報更新を許可
        myLocationManager.allowsBackgroundLocationUpdates = true

        // 初回起動時(位置情報サービス利用許可が設定されていない時)、許可を求めるダイアログを表示
        if (CLLocationManager.authorizationStatus() == .notDetermined) {
            myLocationManager.requestAlwaysAuthorization()
        }

        // 5秒ごとにlocationUpdate()を実行する
        myTimer = Timer.scheduledTimer(timeInterval: Double(5), target: self, selector: #selector(locationUpdate), userInfo: nil, repeats: true)
        myTimer.fire()
    }

    // Timerでループ実行する処理
    @objc func locationUpdate() {
        // 画面のループ処理回数の表示をカウントアップ
        var count: Int = Int(lblTimerCount.text!)!
        count += 1

        // stop -> start で位置情報更新させる
        myLocationManager.stopUpdatingLocation()
        myLocationManager.startUpdatingLocation()

        lblTimerCount.text = String(count)

        // コンソールでバックグラウンドでの処理実行が確認しやすいよう、現在時刻を出力
        let dt = Date()
        let dateFormatter = DateFormatter()

        dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "yMMMdHms", options: 0, locale: Locale(identifier: "ja_JP"))

        print(dateFormatter.string(from: dt))        
        print(count)
    }

    // 位置情報取得成功時
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        print("位置情報取得成功")

        // 以下の処理を書いてたせいで、位置情報取得を止めるだけでなく、
        // 位置情報取得しない -> バックグラウンド処理しない という判断をアプリがするらしい。
        // myLocationManager.stopUpdatingLocation()
    }

    // 位置情報取得失敗時
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("位置情報取得失敗")

        // myLocationManager.stopUpdatingLocation()
    }
}

CoreLocation을 사용한 사람들에게는 잘 알려져 있지만 .startUpdatingLocation 에서 위치 정보를 얻기 시작하면 짧은 시간 내에 여러 차례 위치 정보를 성공적으로 가져오는 (or 실패) 삭제문 이동이 있을 수 있다.
그러면 "Timer의 순환 간격에서 처음 전송문을 이동할 때 위치 정보를 가져오는 것을 멈추면 되지 않습니까?"이렇게 생각하며 델리멘에 .stopUpdatingLocation 을 썼다. 무대 뒤에서 "아, 멈췄어요. 위치 정보를 멈추고 처리하면 무대 뒤에서 멈췄어요."라고 말했다.이렇게 된 거 같은데.
(새 응용 프로그램은 이러한 처리를 통해 백그라운드 처리를 스스로 멈추었다)
이전 응용 프로그램에서는 "위치 정보를 계속 이동합니다. 물론 문을 여러 번 삭제하지만, 지난번 위치 정보에서 xx초 동안 폐기되지 않은 결과를 얻었습니다"라는 처리 방식을 사용했습니다.의식하지 못한 채 백그라운드 처리를 계속하기 위해서다.

감상


백그라운드에서 처리가 안 된다면 주변에 부족한 info를 아무리 설정해도 된다.여러 번 비교하기 쉽지만 이번 일은
なんでバックグラウンド処理したいの?
→位置情報取得したいから
 →(ある処理が動いたら)位置情報取得止める
  →じゃぁバックグランド処理する理由なくなったよね、止めるね。
이런 이치와 행동이 자신의 방식으로 완벽하게 결합되어 이해와 이해가 되어 하루 종일 고민했습니다.
그럼에도 불구하고 낡은 앱을 사용할 때 여기서 고민하지 않아도 되는 자신으로 설계하는 것은 대단하다.

좋은 웹페이지 즐겨찾기