今回の動作確認環境: Xcode 7.2 + Swift 2.1.1 + 実機 iPhone 6 + iOS 9.2
- ピンが上から降ってくるアニメーションをするためには MKMapViewDelegate と MKPinAnnotationView を使う。
- 長押しの処理には UILongPressGestureRecognizer を使う。
- 自動的にフキダシを表示するには MKMapKit.selectAnnotation を使う。
Xcode で新規に Single View Application のプロジェクトを作成して、以下のサンプルコードを ViewController.swift にコピペして、実行するだけでOK。
//
// ViewController.swift
//
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
// 地図
private var myMapView: MKMapView?
// ピン
private var myPin: MKPointAnnotation?
override func viewDidLoad() {
super.viewDidLoad()
// 地図
myMapView = ViewController.createMapView(self.view, delegate: self)
ViewController.setLongPressGesture(myMapView!, parentView: self)
self.view.addSubview(myMapView!)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
private static func createMapView(parentView: UIView, delegate: MKMapViewDelegate) -> MKMapView {
// MKMapView の生成
let mapView = MKMapView()
// MapView のサイズを指定
mapView.frame = parentView.bounds
// MKMapView に Delegate を設定
mapView.delegate = delegate
// 中心点の緯度経度(名古屋駅)
let lat: CLLocationDegrees = 35.1707223
let lon: CLLocationDegrees = 136.882136
let coordinate: CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat, lon)
// 縮尺
let latDist : CLLocationDistance = 100
let lonDist : CLLocationDistance = 100
// Region を生成
let region: MKCoordinateRegion =
MKCoordinateRegionMakeWithDistance(coordinate, latDist, lonDist);
// MKMapView に反映
mapView.setRegion(region, animated: true)
return mapView
}
// 長押しジェスチャーの設定
private static func setLongPressGesture(mapView: MKMapView, parentView: UIViewController) {
let lpg = UILongPressGestureRecognizer()
lpg.addTarget(parentView, action: "onLongPress:")
mapView.addGestureRecognizer(lpg)
}
// 長押しの際の処理
func onLongPress(sender: UILongPressGestureRecognizer) {
// 長押しを認識開始したとき以外は処理しない
if (sender.state != .Began) {
return
}
// 長押しした場所を取得
let location = sender.locationInView(self.myMapView)
// 長押しした場所の緯度・経度に変換
let pos:CLLocationCoordinate2D = self.myMapView!.convertPoint(location, toCoordinateFromView: self.myMapView!)
//ピンを生成
let newPin = MKPointAnnotation()
newPin.coordinate = pos
newPin.title = "長押しした場所"
newPin.subtitle = "緯度,経度: " + pos.latitude.description + "," + pos.longitude.description
// 古いピンを削除
if let pin = self.myPin {
self.myMapView!.removeAnnotation(pin)
}
// 新しいピンを追加
self.myPin = newPin
self.myMapView!.addAnnotation(self.myPin!)
// ピンが表示されたら、自動的にフキダシを表示する
self.myMapView!.selectAnnotation(self.myPin!, animated: true)
}
// ピンが表示される前にコールされる関数
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
// フキダシを表示可能に
pinView?.canShowCallout = true
} else {
pinView?.annotation = annotation
}
return pinView
}
}
-
ref.
- MKMapView Class Reference
- Swift と MapKit で地図アプリを作成する(後編) - koogawa blog ← ピンが上から降ってくるアニメーションの参考に。ピン表示前に処理される viewForAnnotation デリゲートメソッドで、ピンの属性などを設定。
- SwiftでMKMapView上にピン(MKPointAnnotation)置いてみた - Qiita ← 地図上の長押し処理の参考に。UILongPressGestureRecognizer, addGestureRecognizer
- [ヅ] Swift + MapKit で地図アプリの基本的な処理をするサンプルコード (2015-12-15)
tags: Swift map mapkit
Posted by NI-Lab. (@nilab)