SwiftUI 如何在應(yīng)用中使用地圖并在地圖中心位置顯示當(dāng)前的地理位置地址

在現(xiàn)代移動(dòng)應(yīng)用中,地圖功能已經(jīng)成為許多應(yīng)用的重要組成部分。SwiftUI 提供了強(qiáng)大的地圖支持,可以輕松地在應(yīng)用中集成地圖,并結(jié)合位置服務(wù)實(shí)現(xiàn)豐富的地理位置功能。本篇博客將介紹如何使用 SwiftUI 顯示地圖,并在地圖中心位置顯示當(dāng)前的地理位置地址。

功能概述

我們將實(shí)現(xiàn)一個(gè)應(yīng)用,該應(yīng)用包含以下功能:

  • 顯示全屏地圖。
  • 在地圖中心顯示一個(gè)標(biāo)記圖標(biāo)。
  • 實(shí)時(shí)獲取并顯示地圖中心位置的地理地址。

準(zhǔn)備工作

首先,我們創(chuàng)建一個(gè)可觀察的 MapService 類,用于管理地圖狀態(tài)和地理編碼功能。


@Observable
class MapService {
    var currentPosition = MapCameraPosition.userLocation(followsHeading: true, fallback: MapCameraPosition.region(MKCoordinateRegion.init(center: LocationManager.defaultCoordinate, span: LocationManager.defaultCoordinateSpan)))

    var isGeoCoding = false

    var address: String? = nil

    var currentLocation = LocationManager.defaultCoordinate


    func reverGeoCode() {
        self.isGeoCoding = true
        let center = self.currentLocation
        let latitude = center.latitude
        let longitude = center.longitude
        let geoCoder = CLGeocoder()
        let location = CLLocation(latitude: latitude, longitude: longitude)
        geoCoder.reverseGeocodeLocation(location) { (placeMarks, error) in
            self.isGeoCoding = false
            if error != nil {
                self.address = error?.localizedDescription
            }else{
                if let placeMarks, let first = placeMarks.map({$0.description.components(separatedBy: "@").first}).first(where: {$0 != nil}) {
                    self.address = first
                }
            }
        }
    }
}

在 MapService 中,我們使用 @Observable 屬性包裝器使類的屬性的變化能被 SwiftUI 視圖觀察到,并實(shí)現(xiàn)了逆地理編碼的方法 reverseGeoCode。

創(chuàng)建 ContentView 視圖


struct ContentView: View {

    @State private var service = MapService()

    var body: some View {
        ZStack(alignment:.center){
            Map(position: $service.currentPosition,interactionModes: .all)
                .onMapCameraChange({ result in
                    print("\(result.region.center)")
                    service.currentLocation = result.region.center
                    service.reverGeoCode()
                })
            Image(systemName: "mappin")
                .font(.largeTitle)
                .foregroundStyle(.blue)
                .offset(y: -16)
            bottomView
        }
    }

    @ViewBuilder
    var bottomView: some View {
        VStack {
            Spacer()
            VStack {
                HStack{
                    Text("當(dāng)前位置:")
                        .font(.headline)
                        .foregroundColor(.black)
                    Spacer()
                }
                HStack{
                    if service.isGeoCoding {
                        HStack(alignment:.center){
                            Spacer()
                            ProgressView()
                                .progressViewStyle(CircularProgressViewStyle())
                            Spacer()
                        }
                    }else{
                        Text("\(service.address ?? "null")")
                            .font(.body)
                            .foregroundColor(.black)
                            .padding([.bottom,.top,],10)
                    }

                    Spacer(minLength: 10)
                }
            }
            .padding(10)
            .background(.bar)
            .cornerRadius(10)
            .padding()
        }
    }
}

主要部分分析

1.@State:

使用 @State 來管理 MapService 的實(shí)例,使其在視圖生命周期中被正確管理。

2.Map 視圖:

使用 Map 組件顯示地圖,并綁定 position 屬性到 service.position。
通過 onMapCameraChange 方法監(jiān)聽地圖中心位置的變化,并調(diào)用 reverseGeoCode 更新地理位置。

3.中心標(biāo)記圖標(biāo):

使用 Image(systemName: "mappin") 在地圖中心顯示一個(gè)標(biāo)記圖標(biāo)。

4.底部視圖:
使用 @ViewBuilder 構(gòu)建底部視圖,顯示當(dāng)前地理位置或加載指示器。

逆地理編碼功能
在 MapService 中實(shí)現(xiàn)了逆地理編碼功能。每當(dāng)?shù)貓D中心位置發(fā)生變化時(shí),調(diào)用 reverseGeoCode 方法,將地圖中心的坐標(biāo)轉(zhuǎn)換為人類可讀的地址,并更新 UI

運(yùn)行效果

Simulator Screenshot - iPhone 15 Pro - 2024-05-30 at 18.06.52.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容