はじめに
iOSアプリを作ってみたいけど
何から始めて良いのかわからない
とりあえず、
「やってみました」記事を参考に
地図アプリを真似てみようと思う
という記事の7回目です。
今回は、地図を拡大・縮小までします。
拡大・縮小表示
-
比率を定数として定義
- 今回、拡大縮小比に[黄金比]を使います
- ViewController.swift を以下のように修正
-
【なぜ?】
- 1より大きな値であれば、好きな値を選んでOK
- 拡大でも縮小でも使うので、定数(let)とする
- さすが黄金比「いい感じ」で拡大縮小される(と思う)
ViewController.swiftclass ViewController: UIViewController, CLLocationManagerDelegate { let goldenRatio = 1.618 // この行を追加 @IBOutlet var mapView: MKMapView!
-
-
排他(lock)変数を追加
- ViewController.swiftの該当部分を以下のように修正
-
【なぜ?】
- 位置情報の更新や拡大・縮小のため、変数 mapView の値変更を同時に行わないよう排他(lock/unlock)する時に使用するため
- 変数 mapView の値を同時に変更すると、アプリ異常終了の原因となるため
ViewController.swiftclass ViewController: UIViewController, CLLocationManagerDelegate { var myLock = NSLock() // この行を追加 let goldenRatio = 1.618
-
- ViewController.swiftの該当部分を以下のように修正
-
拡大処理
- ViewController.swiftの該当部分を以下のように修正
- 拡大(ZoomIn)処理なので、現在表示している領域より狭い範囲を指定
-
【なぜ?】
- 拡大(ZoomIn)処理の内容を記述する
- 変数 mapView の値を変更するので排他開始(lock)
- mapView.region.span.latitudeDelta の値が表示範囲であるため
- 上記変数の値を小さくしすぎない(今回は、0.005 より大きく制限)
- 上記変数の値を直接変更せずに新規変数を作成(後述)
- regionSpan.latitudeDelta に拡大した時の値を設定
- regionSpan.longitudeDelta は設定しなくて問題ない
- mapView.region.span に regionSpan を設定する(新規変数に置き換える)ことで、地図が拡大される
- 変数 mapView の値変更が終了したので排他解除(unlock)
ViewController.swift@IBAction func clickZoomin(_ sender: Any) { print("[DBG]clickZoomin") myLock.lock() if (0.005 < mapView.region.span.latitudeDelta / goldenRatio) { print("[DBG]latitudeDelta-1 : " + mapView.region.span.latitudeDelta.description) var regionSpan:MKCoordinateSpan = MKCoordinateSpan() regionSpan.latitudeDelta = mapView.region.span.latitudeDelta / goldenRatio mapView.region.span = regionSpan print("[DBG]latitudeDelta-2 : " + mapView.region.span.latitudeDelta.description) } myLock.unlock() }
-
-
縮小処理
- ViewController.swiftの該当部分を以下のように修正
-
【なぜ?】
- 縮小(ZoomOut)処理の内容を記述する
- 縮小(ZoomOut)処理なので、現在表示している領域より広い範囲を指定
- あとは、拡大(ZoomIn)と同様なので説明は省略
ViewController.swift@IBAction func clickZoomout(_ sender: Any) { print("[DBG]clickZoomout") myLock.lock() if (mapView.region.span.latitudeDelta * goldenRatio < 150.0) { print("[DBG]latitudeDelta-1 : " + mapView.region.span.latitudeDelta.description) var regionSpan:MKCoordinateSpan = MKCoordinateSpan() regionSpan.latitudeDelta = mapView.region.span.latitudeDelta * goldenRatio
-
- ViewController.swiftの該当部分を以下のように修正
// regionSpan.latitudeDelta = mapView.region.span.longitudeDelta * GoldenRatio
mapView.region.span = regionSpan
print("[DBG]latitudeDelta-2 : " + mapView.region.span.latitudeDelta.description)
}
myLock.unlock()
}
```
- 位置情報更新時の排他処理追加
- ViewController.swiftの該当部分を以下のように修正
-
【なぜ?】
- GPSの位置情報更新(変数 mapViewの値変更)は、排他が必要な処理だから
ViewController.swiftfunc locationManager(_ manager: CLLocationManager, didUpdateLocations locations:[CLLocation]) { let longitude = (locations.last?.coordinate.longitude.description)! let latitude = (locations.last?.coordinate.latitude.description)! myLock.lock() // この行を追加 mapView.setCenter((locations.last?.coordinate)!, animated: true) myLock.unlock() // この行を追加 }
-
- ViewController.swiftの該当部分を以下のように修正
- テスト実行
- Simulatorを起動し、「+」ボタンや「ー」ボタンを押してみる
- ボタンを押すたびに、地図が拡大・縮小された
今回の到達点
- 拡大・縮小ボタンを押すことで、地図も拡大・縮小するようになった
おまけ
- 実は、今回の記事(ソースコード)は試行錯誤の結果です
- せっかくなので「おまけ」として不採用となった修正を記録に残します
拡大縮小率
- 最初は、2.0 を使っていました
- 縦と横(緯度と経度)がそれぞれ 2.0倍(もしくは1/2倍)される
- その結果、表示される範囲は4倍(もしくは1/4)倍される
- チョット違和感のある拡大・縮小となったので不採用となった
緯度・経度の変数値を直接変更(その1)
- 以下のように mapView.region.span のlatitudeDeltaとlongitudeDeltaを直接変更
ViewController.swift
mapView.region.span.latitudeDelta /= goldenRatio
mapView.region.span.longitudeDelta /= goldenRatio
// 途中省略
mapView.region.span.latitudeDelta *= goldenRatio
mapView.region.span.longitudeDelta *= goldenRatio
- 拡大(ZoomIn)するにはするけど、なぜか倍率は4倍
- latitudeDeltaを変更したら、longitudeDeltaも自動変更されるのだろう
- これで、2倍表示
- longitudeDeltaを変更したら、latitudeDeltaも自動変更されるのだろう
- これで、さらに2倍表示
- 普通に考えたら、緯度だけ(もしくは経度だけ)を拡大縮小することは無いはず
- 縦横(緯度経度)の縮尺が違う地図なんて使い物にならないからね
- latitudeDeltaを変更したら、longitudeDeltaも自動変更されるのだろう
緯度・経度の変数値を直接変更(その2)
- その1の修正をした
- Simulator では、拡大(ZoomIn)するけど、縮小(ZoomOut)しなかった
-
原因は知らない
-
どのように修正すれば良いのか全くわからなかった(ググれ!俺)
-
理由なく、なんとなく、記事のように変数を作成し差し替えるように修正したら動いた
ViewController.swiftvar regionSpan:MKCoordinateSpan = MKCoordinateSpan() regionSpan.latitudeDelta = mapView.region.span.latitudeDelta * goldenRatio mapView.region.span = regionSpan
-
連載
- [はじめてのiOSアプリ]xcodeで地図アプリを作成(その1:プロジェクト作成)
- [はじめてのiOSアプリ]xcodeで地図アプリを作成(その2:地図表示)
- [はじめてのiOSアプリ]xcodeで地図アプリを作成(その3:位置情報取得)
- [はじめてのiOSアプリ]xcodeで地図アプリを作成(その4:位置情報と連携した地図表示)
- [はじめてのiOSアプリ]xcodeで地図アプリを作成(その5:アプリアイコン設定)
- [はじめてのiOSアプリ]xcodeで地図アプリを作成(その6:拡大・縮小ボタン追加)
- [はじめてのiOSアプリ]xcodeで地図アプリを作成(その7:地図を拡大・縮小)
- [はじめてのiOSアプリ]xcodeで地図アプリを作成(その8:地名表示)
- [はじめてのiOSアプリ]xcodeで地図アプリを作成(その9:ソースコード管理)