📍
【SwiftUI】あらかじめ作成したリストからマップ上にピンを打つ
どういうことか
なんらかの住所リストとして、例えば name、address が羅列されたJSONがある。
例えばこんなの👇
spots_data.json
[
{
"id": 1,
"name": "アルサーガパートナーズ株式会社",
"address": "東京都渋谷区道玄坂1丁目12−1"
}
]
MapKit
を使い、こちらのリストの住所の座標にピンを打つ。
JSONをデコード
SpotViewModel
@Published var spots: [Spot] = Bundle.main.decode("spotsData.json")
変換したリストから住所のみを抽出したリストを作る
SpotViewModel
// 住所のみを抽出したリスト
private var addressList: [String] = []
func createAddressList(from spots: [Spot]) {
addressList = spots.compactMap{ $0.address }
}
座標の構造体を作る
CoordinateEntity
import Foundation
import CoreLocation
struct Coordinate: Identifiable {
let id = UUID()
let latitude: Double
let longitude: Double
var coodinate: CLLocationCoordinate2D {
CLLocationCoordinate2D(
latitude: latitude,
longitude: longitude
)
}
}
住所から座標を取得
SpotViewModel
// 座標のリスト
@Published var coordinates: [Coordinate] = []
let geocoder = CLGeocoder()
func fetchCoordinats(addresses: [String]) {
for address in addresses {
geocoder.geocodeAddressString(address) {
placemarks, error in
if let error = error {
print("座標取得エラー; \(error.localizedDescription)")
return
}
if let placemark = placemarks?.first {
if let location = placemark.location {
let coordinate = Coordinate(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
self.coordinates.append(coordinate)
}
}
}
}
}
起動時に呼び出す
SpotViewModel
init() {
createAddressList(from: spots)
fetchCoordinats(addresses: addressList)
}
マップ上にピンを打つ
ContentView
// 中略
// マップの描写
var body: some View {
ZStack {
Map(
coordinateRegion: $region,
annotationItems: viewModel.coordinates,
annotationContent: { spot in
MapAnnotation (coordinate: spot.coodinate) {
ZStack {
SpotIcon()
}
}
}
)
.edgesIgnoringSafeArea(.all)
}
}
(一応)スポットのアイコンは別ファイルで作成したものを使う。
結果、設定した座標にemojiと黒丸が重なったアイコンが表示されるようになる。
SpotIcon
import SwiftUI
struct SpotIcon: View {
var body: some View {
Text("🏢")
.frame(width: 40, height: 40)
.background(Color.yellow)
.cornerRadius(30.0)
.shadow(color: .gray, radius: 3, x: 3, y: 3)
}
}
struct SpotIcon_Previews: PreviewProvider {
static var previews: some View {
SpotIcon()
}
}
実際に表示してみよう
おわり(´・ω・`)
Discussion