対象:
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よりも簡潔な印象を受ける。

GPSから位置情報を取得する(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]) {
        let location = locations.last!
        let latitude = String(format: "%+.06f", location.coordinate.latitude)
        let longitude = String(format: "%+.06f", location.coordinate.longitude)
        let df = NSDateFormatter()
        df.dateFormat = "yyyy/MM/dd HH:mm:ss"
        let timestamp = df.stringFromDate(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 always need your location
	NSLocationWhenInUseUsageDescription
	I need your location when app in use

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


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


更に、iOS 11で若干の仕様変更があり、requestAlwaysAuthorizationするとコンソールに以下のようなメッセージが表示され、位置情報を得ることができなかった。iOS 11でrequestAlwaysAuthorizationするときには、info.plistでNSLocationAlwaysAndWhenInUseUsageDescriptionとNSLocationWhenInUseUsageDescriptionの両方を定義しておかなければならないらしい。らしいというのは、この記事を書いている時点でこの件の公式なドキュメントを見つけることができていないためである。

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
    NSLocationAlwaysAndWhenInUseUsageDescription
    I always need your location
    NSLocationWhenInUseUsageDescription
	I need your location when app in use

(2015/01/28)
() iOS 11対応。

新着情報
【iOS Objective-C, Swift Tips】アプリアイコンにバッジを表示(Swift)
【iOS Objective-C, Swift Tips】画像の向きを指定して保存する(Swift)
【iOS Objective-C, Swift Tips】UIImagePickerControllerの表示を日本語にする(Swift)

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