最近運用していたWebアプリを閉鎖して次に何作ろうか考え中のhokです。
一個前に作成したのがWebアプリだったので、次はスマホアプリを開発しようと思いサンプルで iOS地図(Map)アプリを作りました。
自分への備忘録としてiOS 地図アプリ実装方法を残します。
地図スマホアプリ仕様 見出しへのリンク
以下仕様の地図アプリを作成しました。
- 自分の位置の地図を表示させる
- 画面をロングタップするとピンを留めることができる
- ピン留めした箇所は任意の画像(牛)で表示する
- そのピンを押すと、タイトル[LongPressPin],サブタイトル[sub],右側に OK ボタンを表示させる
- OK ボタンを押すと「OK ボタン押下後 OK ボタン押下後のポップアップ」と記載されたポップアップを表示させる
開発環境 見出しへのリンク
- Swift 5.1
- Xcode 11.1
実装 ViewController.swift 見出しへのリンク
import UIKit
import MapKit
import CoreLocation
struct Annotation {
let address: String
let title: String?
let subtitle: String?
}
class ViewController: UIViewController {
@IBOutlet weak var mapView: MKMapView!
var myLocationManager:CLLocationManager!
//ロングタップしたときに立てるピンを定義
var pinByLongPress:MKPointAnnotation!
// ViewControllerのviewがロードされた後
override func viewDidLoad() {
super.viewDidLoad()
configureSubviews()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// 完全に遷移が行われ、スクリーン上に表示された時
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
startUpdatingLocation()
}
// 初期設定
private func configureSubviews() {
// CLLocationManagerのインスタンス生成
myLocationManager = CLLocationManager()
myLocationManager.delegate = self
myLocationManager.desiredAccuracy = kCLLocationAccuracyBest
myLocationManager.distanceFilter = 100
myLocationManager.startUpdatingLocation()
// MKMapViewのdelegate
mapView.delegate = self
mapView.mapType = .standard
mapView.userTrackingMode = .follow
}
private func startUpdatingLocation() {
switch CLLocationManager.authorizationStatus() {
case .notDetermined:
myLocationManager.requestWhenInUseAuthorization()
default:
break
}
myLocationManager.startUpdatingLocation()
}
//ロングタップを感知したときに呼び出されるメソッド
@IBAction func longPressMap(_ sender: UILongPressGestureRecognizer) {
if(sender.state != UIGestureRecognizer.State.began){
return
}
//ロングタップから位置情報を取得
let location:CGPoint = sender.location(in: mapView)
//取得した位置情報をCLLocationCoordinate2D(座標)に変換
let longPressedCoordinate:CLLocationCoordinate2D = mapView.convert(location, toCoordinateFrom: mapView)
// インスタンス作成
pinByLongPress = MKPointAnnotation()
//ロングタップした位置の座標をピンに入力
pinByLongPress.coordinate = longPressedCoordinate
pinByLongPress.title = "LongPressPin"
pinByLongPress.subtitle = "sub"
//ピンを追加する(立てる)
mapView.addAnnotation(pinByLongPress)
}
}
// MARK: - MKMapViewDelegate
extension ViewController: MKMapViewDelegate {
// アノテーションビューを返すメソッド
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// 現在地表示かピンか区別
if annotation is MKUserLocation {
return nil
}
let pinView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: nil)
pinView.glyphImage = UIImage(named:"pinImage")!
// 吹き出しを表示可能にする
pinView.canShowCallout = true
let button = UIButton()
button.frame = CGRect(x:0,y:0,width:40,height:40)
button.setTitle("OK", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.backgroundColor = UIColor.green
button.addTarget(self, action: #selector(sendLocation), for: .touchUpInside)
// 右側にボタンを追加
pinView.rightCalloutAccessoryView = button
return pinView
}
// OKボタン押下時の処理
@objc func sendLocation(){
let alert = UIAlertController(title: "OKボタン押下後", message: "OKボタン押下後のポップアップ", preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title:"OK", style: .default, handler: { (_) in
self.dismiss(animated: true, completion: nil)
}))
present(alert, animated: true, completion: nil)
}
}
// MARK: - CLLocationManagerDelegate
extension ViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("位置情報の取得に成功しました")
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
let alert = UIAlertController(title: nil, message: "位置情報の取得に失敗しました", preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "OK", style: .default, handler: { (_) in
self.dismiss(animated: true, completion: nil)
}))
present(alert, animated: true, completion: nil)
}
}