MapKit问题:SwiftUI(Xcode15)无法通过变量获取路线信息
解决SwiftUI地图应用路线信息存储与Sheet展示问题
核心问题分析
你当前的代码存在两个关键问题:
- 在
Map视图闭包内定义的var myRoute是局部临时变量,仅在该闭包的单次构建周期内有效,无法被外部(比如Sheet)访问。 - 点击"Show Sheet"按钮时使用强制解包
!获取路线信息,当route为nil时会直接崩溃,存在安全隐患。
解决方案
我们需要在获取路线数据的时机直接更新全局状态变量,同时避免强制解包:
- 移除无效局部变量:删除
Map闭包内的var myRoute = route.steps.map...代码,SwiftUI的body是视图构建区域,不适合在此修改状态变量。 - 路线计算后同步更新状态:在
getDirections函数中,获取到route后直接将步骤指令转换为字符串数组存入directions变量。 - 优化Sheet触发逻辑:点击按钮时只需切换
showDirections状态,无需重复处理路线数据。
修改后的完整代码
import SwiftUI import MapKit extension CLLocationCoordinate2D { static let parking = CLLocationManager().location?.coordinate // CLLocationCoordinate2D(latitude: 42.354528, longitude: -71.068369) } struct ContentView: View { @State private var position: MapCameraPosition = .automatic @State private var visibleRegion: MKCoordinateRegion? @State private var searchResults: [MKMapItem] = [] @State private var selectedResult: MKMapItem? @State private var route: MKRoute? @State private var showDirections = false @State private var directions: [String] = [] @State private var myLocation = CLLocationManager().location?.coordinate @StateObject private var viewModel = ContentViewModel() var body: some View { Map(position: $position, selection: $selectedResult) { ForEach(searchResults, id: \.self) { result in Marker(item: result) } .annotationTitles(.hidden) UserAnnotation() if let route { MapPolyline(route) .stroke(.blue, lineWidth: 5) var _ = print("ROUTE = \(route.steps.map { $0.instructions }.filter { !$0.isEmpty })") } } .onAppear() { viewModel.checkIfLocationServicesIsEnabled() } .mapStyle(.standard(elevation: .realistic)) .safeAreaInset(edge: .bottom) { HStack { Spacer() VStack(spacing: 0) { if let selectedResult { ItemInfoView(selectedResult: selectedResult, route: route) .frame(height: 128) .clipShape(RoundedRectangle(cornerRadius: 10)) .padding([.top, .horizontal]) } Button("Show Sheet") { showDirections.toggle() } .sheet(isPresented: $showDirections) { VStack(spacing: 0) { Text("Directions") .font(.largeTitle) .bold() .padding() Divider().background(Color(UIColor.systemBlue)) List(directions, id: \.self) { instruction in Text(instruction).padding() } Button("Dismiss") { showDirections.toggle() } .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(10) } .padding() } .padding() POI(position: $position, searchResults: $searchResults, visibleRegion: visibleRegion) .padding(.top) .frame(width: 350, height: 100) } Spacer() } .background(.thinMaterial) } .onChange(of: searchResults) { position = .automatic } .onChange(of: selectedResult) { getDirections() } .onMapCameraChange { context in visibleRegion = context.region } .mapControls { MapUserLocationButton() MapCompass() MapScaleView() } } func getDirections() { route = nil directions.removeAll() guard let selectedResult, let parkingCoordinate = CLLocationCoordinate2D.parking else { return } let request = MKDirections.Request() request.source = MKMapItem(placemark: MKPlacemark(coordinate: parkingCoordinate)) request.destination = selectedResult Task { let directions = MKDirections(request: request) guard let response = try? await directions.calculate(), let route = response.routes.first else { print("Failed to calculate route") return } self.route = route self.directions = route.steps.map { $0.instructions }.filter { !$0.isEmpty } print("COUNT = \(self.directions.count)") } } } // 补充缺失的视图定义以保证编译通过 struct ContentViewModel: ObservableObject { func checkIfLocationServicesIsEnabled() {} } struct ItemInfoView: View { let selectedResult: MKMapItem let route: MKRoute? var body: some View { Text(selectedResult.name ?? "Unknown Location") } } struct POI: View { @Binding var position: MapCameraPosition @Binding var searchResults: [MKMapItem] let visibleRegion: MKCoordinateRegion? var body: some View { TextField("Search", text: .constant("")) } } #Preview { ContentView() }
关键修改点说明
- 在
getDirections中增加parking坐标的可选绑定,避免强制解包崩溃。 - 路线计算成功后直接将处理好的指令数组赋值给
@State var directions,确保数据及时同步。 - Sheet中的List改为直接遍历
directions数组,代码更简洁安全。 - 移除所有不必要的局部变量和强制解包操作,提升代码稳定性。
内容的提问来源于stack exchange,提问作者user427196
相关产品推荐
相关产品推荐

