「ゴルトン社長」のはじめの一歩

すげーブログ

世の中のすげーを伝える!

【iphoneアプリ開発_初心者必見】地図を表示してみよう!! (MapKitの基礎・基本)

最終更新日:2020年08月14日
f:id:BlueThree:20200814204123j:plain:w500
家に引きこもっている「ゴルトン社長」です。(twitter : @GoRuton_1stStep)

地図を表示してみよう!! (MapKitの基礎・基本)

  • 地図アプリは単に地図として使われたり,他の機能と組み合わせて使うなど様々な用途があります
  • ここでは基本的な現在地の位置情報を示す地図アプリを作成してみましょう

人気の記事!

人生を変えたい人に向けて「はじめの一歩」を踏み出したい人にオススメ!

www.goruton.com www.goruton.com www.goruton.com www.goruton.com

1) フレームワークの導入

MapKitとCoreLocationの2つのフレームワークを導入します

f:id:BlueThree:20190629094455p:plain
フレームワークの導入

  • Map(プロジェクト名) を選択
  • TARGETS (Map) を選択
  • 右上の Build Phases を選択
  • 4つの▶で始まる項目が表示される
  • Link Binary With Libraries のところの▶をクリックして展開
  • +マークを押してください。
  • MapKit と入力して検索
  • MapKit.framework という名前のフレームワークが表示されるので、それを選択してAdd!
  • 同じ手順で CoreLocation.framework もAddしてください。
2) 位置情報の利用の許可のリクエストの実装と現在地の表示

f:id:BlueThree:20190629094553p:plain:h300:w200
許可のリクエストの実装

  • 現在地を取得、表示するためにユーザーに位置情報の利用の許可をリクエストする必要があります。
  • この機能を実装し、ユーザーに許可をもらえないと現在地の取得、表示はできません。
  • Xcodeの画面の一番左のファイルの階層などを表しているところの info.plist にカーソルを合わせ右クリック(副クリック), OpenAs ▶SourceCode を選択してください。
  • プロパティリストがソースコードで表示されます。
  • dict のタグで囲まれなかに key として NSLocationWhenInUseUsageDescriptionを、Stringには任意の文字列を以下のように入れます

info.plist

<plist version="1.0">
<dict>

    //省略

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>位置情報をこのアプリの起動時に使います</string>
</dict>
</plist>
3)実際のコードと実装
  • はじめにストーリーボードにMapViewを配置して、配置したMapViewをコードと紐付けし,画面いっぱいに広げてください

  • その後,ViewController.swiftに下記のように記述してください

ViewController.swift

import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate{

    @IBOutlet weak var testMapView: MKMapView!

    //CLLocationManagerの入れ物を用意
    var myLocationManager:CLLocationManager!

    override func viewDidLoad() {

        super.viewDidLoad()

        //CLLocationManagerをインスタンス化
        myLocationManager = CLLocationManager()


        //位置情報使用許可のリクエストを表示するメソッドの呼び出し
        myLocationManager.requestWhenInUseAuthorization()

    }

    //位置情報取得に失敗したときに呼び出されるメソッド
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("error")
    }

}
  • class ViewController:UIViewController に続けて,CLLocationManagerDelegate を追記します。
  • CLLocationManagerDelegate には許可のステータスが変更されたときに呼び出されるメソッドが定義されています。
  • このメソッドをViewController実装することで変更後の許可のステータスを受け取ることができます。
  • MapViewを紐付けしたところの下にCLLocationManagerの入れ物を定義します。
  • viewdidloadの中でCLLocationManagerをインスタンス化することでCLLocationManagerに含まれるメソッドを使えるようにします。
  • その次にCLLocationManagerのメソッドのひとつのrequestWhenInUseAuthorization()を呼び出します。
  • この記述をすることでアプリ使用時の位置情報の利用の許可をユーザーにリクエストできます。

f:id:BlueThree:20190629094716p:plain
MainStoryBoard

  • 画面左のMain.storyboardを選択
  • 画面右側のShow the Attributes inspectorを選択
  • User Locationのチェックを入れる

f:id:BlueThree:20190629095215p:plain
実装画面

  • command+Rで実装して,画像のようになっているか確認してください

目次2

位置情報の表示アプリの作成

1)特定の位置を表示
2)ピンの様々な表示方法
1)特定の位置を表示
  • ViewController.swiftに下記のコードを記述してください

ViewController.swift

import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate{
    

    @IBOutlet weak var mapView: MKMapView!
    
    //CLLocationManagerの入れ物を用意
    var myLocationManager:CLLocationManager!
    
    override func viewDidLoad() {
        
        super.viewDidLoad()
        /*アップル本社周辺(緯度37.331652997806785, 経度-122.03072304117417)を表示*/
        let coordinate = CLLocationCoordinate2DMake(37.331652997806785, -122.03072304117417)
        let span = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)
        let region = MKCoordinateRegion(center: coordinate, span: span)
        mapView.setRegion(region, animated:true)
    }
    
    //位置情報取得に失敗したときに呼び出されるメソッド
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("error")
    }
    
}
  • 表示したい位置を CLLocationCoordinate2DMake メソッドで指定
  • 今回はアップル本社周辺(緯度37.331652997806785, 経度-122.03072304117417)を表示
  • 表示する範囲を MKCoordinateSpanMake メソッドで指定
  • 数値が小さくなるほど表示される領域は狭くなります。(ズームレベルが高くなる)
  • 「位置」と「表示範囲」から Region オブジェクトを生成し、MapViewにセット
  • command+Rで実装して,アップル本社周辺が表示されたか確認してください
2)ピンの様々な表示方法
  • 地図上にピンを表示していきます。
  • このパートで使用する全体のサンプルコードを以下に示します

ViewController.swift

import UIKit
import MapKit

class ViewController: UIViewController, MKMapViewDelegate {
    
    @IBOutlet weak var mapView: MKMapView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view, typically from a nib.
        let coordinate = CLLocationCoordinate2DMake(37.331652997806785, -122.03072304117417)
        let span = MKCoordinateSpan.init(latitudeDelta: 0.003, longitudeDelta: 0.003)
        let region = MKCoordinateRegion.init(center: coordinate, span: span)
        mapView.setRegion(region, animated:true)
        
        // ピンを表示する タイトルを指定する
        let annotation = MKPointAnnotation()
        annotation.coordinate = coordinate
        annotation.title = "title"
        annotation.subtitle = "subtitle"
        self.mapView.addAnnotation(annotation)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // MARK: - MKMapView delegate
    // Called when the region displayed by the map view is about to change
    func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
        print(#function)
    }
    
    // Called when the annotation was added
    //ピンにアニメーションをつける
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        if annotation is MKUserLocation {
            return nil
        }
        
        let reuseId = "pin"
        var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
        if pinView == nil {
            pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
            pinView?.animatesDrop = true
            pinView?.canShowCallout = true
            pinView?.isDraggable = true
            
            //ピンに色を表示する
            pinView?.pinColor = .purple
            
            let rightButton: AnyObject! = UIButton(type: UIButton.ButtonType.detailDisclosure)
            pinView?.rightCalloutAccessoryView = rightButton as? UIView
        }
        else {
            pinView?.annotation = annotation
        }
        
        return pinView
    }
    
    //バルーンにボタンをつけてみる
    func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
        print(#function)
        if control == view.rightCalloutAccessoryView {
            performSegue(withIdentifier: "toTheMoon", sender: self)
        }
    }
    
    func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, didChange newState: MKAnnotationView.DragState, fromOldState oldState: MKAnnotationView.DragState) {
        if newState == MKAnnotationView.DragState.ending {
            let droppedAt = view.annotation?.coordinate
            print(droppedAt.debugDescription)
        }
    }
    
    // MARK: - Navigation
    @IBAction func didReturnToMapViewController(_ segue: UIStoryboardSegue) {
        print(#function)
    }
}
ピンを表示する, ピンのタイトルを指定する
  • 地図上にピンを表示するため,MKPointAnnotation オブジェクトを使用
  • coordinate プロパティにピンを表示する緯度経度を指定
  • MapView に addAnnotation メソッドで追加
  • MKPointAnnotation クラスはプロパティに title と subtitle を持っている
  • 文字列を指定することで、ピンをタップした時にタイトルを表示するバルーンを出すことが可能
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
annotation.title = "title"
annotation.subtitle = "subtitle"
self.mapView.addAnnotation(annotation)
ピンにアニメーションを付ける

ピンが上から降ってくるようにしてみます。

  • MapView のデリゲートを ViewController.swift にセットします。
  • Story Board で MapView を選択
  • 画面右側の「Connections Inspector」にある delegate の ○ と、画面左側の View Controller をドラッグアンドドロップで結びつけます。
  • MapView のデリゲートメソッドを実装していきます。
  • クラス宣言部に MKMapViewDelegate を追記します。
class ViewController: UIViewController, MKMapViewDelegate {

===========
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
    if annotation is MKUserLocation {
        return nil
    }

    let reuseId = "pin"
    var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
    if pinView == nil {
        pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
        pinView?.animatesDrop = true
    }
    else {
        pinView?.annotation = annotation
    }
        
    return pinView
}
  • viewForAnnotation デリゲートメソッドを実装します。
  • このメソッドはピンが画面に表示する直前に呼ばれ、今から表示するピンの属性や外観などをMKPinAnnotationView オブジェクトを使って指定することができます。
  • ピンは何度も再利用されます(UITableViewCell のようなイメージ)。
  • dequeueReusableAnnotationViewWithIdentifier で再利用できるピンを取り出します。
  • 再利用できるものがなければ新たに作成します。
  • アニメーションを付けるには animatesDrop プロパティに true を指定します。
ピンの色を変更する
  • ピンの色はデフォルトで赤
  • MKPinAnnotationView の pinTintColor プロパティをセットすることで好きな色に変更できます。
pinView?.pinColor = .purple
バルーンにボタンを付けてみる
  • バルーンに UIButton を付けることもできます。
  • MKPinAnnotationView の canShowCallout プロパティを true にセットします。
  • これをやらないとバルーンが表示されないので注意してください。
pinView?.canShowCallout = true

let rightButton: AnyObject! = UIButton(type: UIButtonType.DetailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
  • ボタンがタップされると calloutAccessoryControlTapped デリゲートが呼ばれます。
  • ここに必要な処理を書いていくと良いでしょう。
func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
    print(__FUNCTION__)
}

参考リンク

最後に!!

f:id:BlueThree:20200805191056j:plain:w500

最後までご覧いただき、本当にありがとうございます!!

最近は、たくさんの読者さんから「コメント」や「メッセージ」が届くようになりました!!
皆さんと会話できて嬉しいですし、コメントで毎日励まされています。

ありがとうございます!

これからも、ゴルトン社長は「毎日」ブログを更新しています! www.goruton.com www.goruton.com www.goruton.com www.goruton.com www.goruton.com

皆さんから人気がある記事

www.goruton.com www.goruton.com www.goruton.com www.goruton.com www.goruton.com

まとめ記事

www.goruton.com www.goruton.com www.goruton.com www.goruton.com www.goruton.com www.goruton.com www.goruton.com