4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[はじめてのiOSアプリ]xcodeで地図アプリを作成(その7)

Last updated at Posted at 2019-12-10

はじめに

iOSアプリを作ってみたいけど
何から始めて良いのかわからない

とりあえず、
「やってみました」記事を参考に
地図アプリを真似てみようと思う

という記事の7回目です。

今回は、地図を拡大・縮小までします。

拡大・縮小表示

  1. 比率を定数として定義

    • 今回、拡大縮小比に[黄金比]を使います
    • ViewController.swift を以下のように修正
      • 【なぜ?】

        • 1より大きな値であれば、好きな値を選んでOK
        • 拡大でも縮小でも使うので、定数(let)とする
        • さすが黄金比「いい感じ」で拡大縮小される(と思う)
        ViewController.swift
        class ViewController: UIViewController, CLLocationManagerDelegate {
            let goldenRatio = 1.618  // この行を追加
        
            @IBOutlet var mapView: MKMapView!
        
  2. 排他(lock)変数を追加

    • ViewController.swiftの該当部分を以下のように修正
      • 【なぜ?】

        • 位置情報の更新や拡大・縮小のため、変数 mapView の値変更を同時に行わないよう排他(lock/unlock)する時に使用するため
        • 変数 mapView の値を同時に変更すると、アプリ異常終了の原因となるため
        ViewController.swift
        class ViewController: UIViewController, CLLocationManagerDelegate {
            var myLock = NSLock()  // この行を追加
            let goldenRatio = 1.618
        
  3. 拡大処理

    • 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()
        }
        
  4. 縮小処理

    • 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
        

// regionSpan.latitudeDelta = mapView.region.span.longitudeDelta * GoldenRatio
mapView.region.span = regionSpan
print("[DBG]latitudeDelta-2 : " + mapView.region.span.latitudeDelta.description)
}
myLock.unlock()
}
```

  1. 位置情報更新時の排他処理追加
    • ViewController.swiftの該当部分を以下のように修正
      • 【なぜ?】

        • GPSの位置情報更新(変数 mapViewの値変更)は、排他が必要な処理だから
        ViewController.swift
        func 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()  // この行を追加
        }
        
  2. テスト実行
    • 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倍表示
    • 普通に考えたら、緯度だけ(もしくは経度だけ)を拡大縮小することは無いはず
      • 縦横(緯度経度)の縮尺が違う地図なんて使い物にならないからね

緯度・経度の変数値を直接変更(その2)

  • その1の修正をした
  • Simulator では、拡大(ZoomIn)するけど、縮小(ZoomOut)しなかった
    • 原因は知らない

    • どのように修正すれば良いのか全くわからなかった(ググれ!俺)

    • 理由なく、なんとなく、記事のように変数を作成し差し替えるように修正したら動いた

      ViewController.swift
      var regionSpan:MKCoordinateSpan = MKCoordinateSpan()
      regionSpan.latitudeDelta = mapView.region.span.latitudeDelta * goldenRatio
      mapView.region.span = regionSpan
      

連載

  1. [はじめてのiOSアプリ]xcodeで地図アプリを作成(その1:プロジェクト作成)
  2. [はじめてのiOSアプリ]xcodeで地図アプリを作成(その2:地図表示)
  3. [はじめてのiOSアプリ]xcodeで地図アプリを作成(その3:位置情報取得)
  4. [はじめてのiOSアプリ]xcodeで地図アプリを作成(その4:位置情報と連携した地図表示)
  5. [はじめてのiOSアプリ]xcodeで地図アプリを作成(その5:アプリアイコン設定)
  6. [はじめてのiOSアプリ]xcodeで地図アプリを作成(その6:拡大・縮小ボタン追加)
  7. [はじめてのiOSアプリ]xcodeで地図アプリを作成(その7:地図を拡大・縮小)
  8. [はじめてのiOSアプリ]xcodeで地図アプリを作成(その8:地名表示)
  9. [はじめてのiOSアプリ]xcodeで地図アプリを作成(その9:ソースコード管理)
4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?