しろかい!

アプリ開発や機械学習などの開発Tips.

Swiftで現在地の位置情報をGPSで取得する時に最低限しないといけないこと

swiftで現在地を取得する方法は既にネット上にも情報があるのだが,ページによって方法が若干異なってたり,ページに書いてある通りに実行しても何かとつまづくことが多い.
そこで本エントリーでは,現在地取得に最低限必要なことだけに限って説明し,現在地を取得してログに表示するサンプルを実行する方法を紹介する.

【Swift3系を利用する方へ】 (2016/9/18更新)
Swift3で以下の内容を実装する場合は、ViewController.swiftの内容を一部変更する必要があるようです。
詳しくは、コチラのコメントを参照してください。

1. 新規プロジェクトの作成

  • Applicationの種類はSingle View Applicationを選択.(別に何でも構わない)
  • LanguageはSwiftを選択.
  • 他の設定は適当で構わない.

2. ViewController.swiftの編集

以下のコードに書き換える.
現在地の取得に最低限必要な部分以外はコメントアウトしておいた.

import UIKit
import CoreLocation

// CLLocationManagerDelegateを継承しなければならない
class ViewController: UIViewController, CLLocationManagerDelegate {
    
    // 現在地の位置情報の取得にはCLLocationManagerを使用
    var lm: CLLocationManager!
    // 取得した緯度を保持するインスタンス
    var latitude: CLLocationDegrees!
    // 取得した経度を保持するインスタンス
    var longitude: CLLocationDegrees!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // フィールドの初期化
        lm = CLLocationManager()
        longitude = CLLocationDegrees()
        latitude = CLLocationDegrees()
        
        // CLLocationManagerをDelegateに指定
        lm.delegate = self

        // 位置情報取得の許可を求めるメッセージの表示.必須.
        lm.requestAlwaysAuthorization()
        // 位置情報の精度を指定.任意,
        // lm.desiredAccuracy = kCLLocationAccuracyBest
        // 位置情報取得間隔を指定.指定した値(メートル)移動したら位置情報を更新する.任意.
        // lm.distanceFilter = 1000
        
        // GPSの使用を開始する
        lm.startUpdatingLocation()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    /* 位置情報取得成功時に実行される関数 */
    func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation){
        // 取得した緯度がnewLocation.coordinate.longitudeに格納されている
        latitude = newLocation.coordinate.latitude
        // 取得した経度がnewLocation.coordinate.longitudeに格納されている
        longitude = newLocation.coordinate.longitude
        // 取得した緯度・経度をLogに表示
        NSLog("latiitude: \(latitude) , longitude: \(longitude)")
        
        // GPSの使用を停止する.停止しない限りGPSは実行され,指定間隔で更新され続ける.
        // lm.stopUpdatingLocation()
    }
    
    /* 位置情報取得失敗時に実行される関数 */
    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        // この例ではLogにErrorと表示するだけ.
        NSLog("Error")
    }
    
}

3. Info.plistの編集

次の値を追加する.

  • Key: NSLocationAlwaysUsageDescription
  • Type: String
  • Value: Use CoreLocation!

なお,Info.plistはSupporting Filesフォルダの中にある.
下記画像のように,適当なKeyをクリックすると「+」マークが現れるので,それを押す.

f:id:shun9167:20141213004933p:plain

すると,以下のように新たな値を追加できるようになるので,上記の値を入力する.

f:id:shun9167:20141213005209p:plain

4. 実行

ここまでできたら実行してみる.
まず,位置情報取得の許可を求めるダイアログが表示されるので,許可する.
するとログに次のように表示される.

2014-12-13 00:56:52.797 LocationSample[20171:546089] Error

どうやら現在地が取得できていないようだ.これは,iOSシミュレータ*1に仮想の現在地を指定してやることで解決する.
方法は簡単で,iOSシミュレータのDebug->Locationから任意の場所を選択するだけ.
すると,ログに以下のように表示され,正常に現在地を取得できていることが分かる.

2014-12-13 00:59:46.018 LocationSample[20171:546089] latiitude: 37.3326172860087 , longitude: -122.030379948992

まとめ

今回は現在地取得にフォーカスするために,Viewは一切触れずにログに現在地を表示するサンプルを示した.
よくつまづく点は,次の3つ.

  • requestAlwaysAuthorization()を呼び出す必要がある.
  • Info.plistにNSLocationAlwaysUsageDescriptionを追加する.
  • iOSシミュレータのLocationを設定する.

なお,他のページでは「Link Binary With Libraries」に「CoreLocation.framework」を追加する必要があると書かれてたりするが,これは必要ないようだ.

その他,細かいことはソースコード上にコメントを書いてあるので,そちらを参考にしてください.

*1:実機で実行した場合はErrorは出ないはず.