対象:
Swift4

GPSから位置情報を取得する(Swift)

iOSでGPSから現在位置を取得するために必要な事は概ね以下になる。

  1. CoreLocationをimport
  2. ViewControllerクラスでCLLocationManagerDelegateを継承
  3. locationManager:didUpdateLocationsデリゲートメソッドを作成
  4. CLLocationManagerのインスタンスを生成
  5. 生成したインスタンスにデリゲート割り当て
  6. 生成したインスタンスのstartUpdatingLocationメソッド呼び出し

SwiftでGPSから位置情報を取得する場合も、必要なことは本質的にObjective-Cの場合と同じである。しかし、Swiftの場合CoreLocation.frameworkのリンクは不要で、かつコードもallocやらinitやらがない分Objective-Cよりも簡潔な印象を受ける。

まず、ViewController.swiftの冒頭でCoreLocationをimportする。

import UIKit
import CoreLocation

そして、CLLocationManager型のプロパティを、例えばlocationManagerという名前でViewControllerクラスに用意する。ViewControllerクラスでは、CLLocationManagerDelegateを継承する。これによって、locationManager:didUpdateLocationsデリゲートメソッドで位置情報を受け取ることができるようになる。

class ViewController: UIViewController, CLLocationManagerDelegate {
    var locationManager: CLLocationManager!

locationManager:didUpdateLocationsデリゲートメソッドをViewControllerクラスに追加する。ViewControllerクラスの空いているところでlocationの頭文字"l"を入力すると、locationManager等の候補が表示されるはずなので、didUpdateLocationsのものを選択すれば簡単に追加できるだろう。

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

viewDidLoadメソッドでCLLocationManagerのインスタンスを生成する。生成したインスタンスのdelegateプロパティにViewControllerクラス自身を割り当てる。最後にstartUpdatingLocationメソッドを呼び出して情報の更新を開始すれば、端末で位置情報を取得することができる。

コード全体を以下に示す。因みにlabelLatitude、labelLongitude、及びlabelTimeは、それぞれ緯度、経度、及び受信時刻を表示するためのLabelのReferencing outletである。

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {
    var locationManager: CLLocationManager!
    @IBOutlet weak var labelLatitude: UILabel!
    @IBOutlet weak var labelLongitude: UILabel!
    @IBOutlet weak var labelTime: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        if locationManager == nil {
            locationManager = CLLocationManager()
            if #available(iOS 8.0, *) {
                // NSLocationWhenInUseUsageDescriptionに設定したメッセージでユーザに確認
                locationManager.requestWhenInUseAuthorization()
                // NSLocationAlwaysAndWhenInUseUsageDescriptionに設定したメッセージでユーザに確認
                //locationManager.requestAlwaysAuthorization()
            }
        }
        locationManager.delegate = self
        locationManager.startUpdatingLocation()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if let location = locations.last {
            let latitude = String(format: "%+.06f", location.coordinate.latitude)
            let longitude = String(format: "%+.06f", location.coordinate.longitude)
            let df = DateFormatter()
            df.dateFormat = "yyyy/MM/dd HH:mm:ss"
            let timestamp = df.string(from: location.timestamp)
            print("\(timestamp) \(latitude) \(longitude)")
            labelLatitude.text = latitude
            labelLongitude.text = longitude
            labelTime.text = timestamp
        }
    }
}

locationManager:didUpdateLocationsデリゲートメソッドは位置情報の更新があったときに呼ばれる。locations引数はCLLocationの配列で、末尾が最新の位置情報であるので、これを取り出して緯度、及び経度を得ることができる。位置情報の更新間隔はdistanceFilterプロパティである程度制御できる。

尚、iOS 8以降(iOS 11以降については後述)の場合、以下が必要になることを改めて記載しておく。生成したロケーションマネージャでrequestWhenInUseAuthorizationメソッド、またはrequestAlwaysAuthorizationメソッドを呼び出し、ユーザから位置情報の利用について承認を得なければならない。

            if #available(iOS 8.0, *) {
                // NSLocationWhenInUseUsageDescriptionに設定したメッセージでユーザに確認
                locationManager.requestWhenInUseAuthorization()
                // NSLocationAlwaysUsageDescriptionに設定したメッセージでユーザに確認
                //locationManager.requestAlwaysAuthorization()
            }

これに先立って、2つのメソッドがそれぞれユーザに承認を得るときに利用するメッセージを予めInfo.plistで定義しておく必要がある。

	NSLocationAlwaysUsageDescription
	I will always need your location
	NSLocationWhenInUseUsageDescription
	I will need your location when app in use

作成したアプリを実行すると、以下のような確認メッセージが表示される。(iOS 11でアプリ実行)


尚、この設定は端末の[設定] > [アプリ名(恐らく下のほうで見つかる)] > [位置情報]で変更できる。(iOS 11でアプリ実行)


更に、iOS 11で若干の仕様変更があり、requestAlwaysAuthorizationするとコンソールに以下のようなメッセージが表示され、位置情報を得ることができなかった。iOS 11でrequestAlwaysAuthorizationするときには、Info.plistでNSLocationAlwaysAndWhenInUseUsageDescriptionとNSLocationWhenInUseUsageDescriptionの両方を定義しておかなければならない。iOS 11だけでなく、iOS 10以下にも対応する必要があるなら、NSLocationAlwaysUsageDescriptionも合わせて定義しておくと良い。

This app has attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain both NSLocationAlwaysAndWhenInUseUsageDescription and NSLocationWhenInUseUsageDescription keys with string values explaining to the user how the app uses this data
	NSLocationAlwaysUsageDescription
	I will always need your location
	NSLocationWhenInUseUsageDescription
	I will need your location when app in use
	NSLocationAlwaysAndWhenInUseUsageDescription
	I will always need your location

(2015/01/28)
() iOS 11関連の修正。

新着情報
【オープンソースソフトウェア環境構築】Apple silicon Macで開発環境を構築
【Rust Tips】Actix webでJSONをPOSTする
【Rust Tips】コマンドライン引数を取得する

Copyright© 2004-2019 モバイル開発系(K) All rights reserved.
[Home]