対象: GPSから位置情報を取得する(Swift)iOSでGPSから現在位置を取得するために必要な事は概ね以下になる。
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で定義しておく必要がある。
作成したアプリを実行すると、以下のような確認メッセージが表示される。(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
(2015/01/28) () iOS 11関連の修正。
Copyright© 2004-2019 モバイル開発系(K) All rights reserved.
[Home]
|