swiftui - 如何将数据从地图注释传输到全屏封面弹出窗口
问题描述
用户单击 MapAnnotation 后,我正在尝试传输数据。目前,在用户单击 MapAnnotation 后,它会将数据添加到 selectedCourse 并在开始之前打印它,如果 let course = selectedCourse。但是由于某些原因 selectedCourse 在 .fullScreenCover if 语句中为空
import SwiftUI
import MapKit
struct CourseMapView: View {
@ObservedObject var viewModel: CourseSearchViewModel
@State var isShowSheet = false
@State var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 60.480960,
longitude: 22.239808),
span: MKCoordinateSpan(latitudeDelta: 0.1,
longitudeDelta: 0.1))
@State var selectedCourse: Course? = nil
func setCurrentLocation() {
region = MKCoordinateRegion(center: viewModel.location?.coordinate ?? CLLocationCoordinate2D(latitude: 60.480960, longitude: 22.239808), span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
}
var body: some View {
ZStack {
if viewModel.location != nil {
Map(coordinateRegion: $region, interactionModes: .all, showsUserLocation: true, userTrackingMode: nil, annotationItems: viewModel.courses) { course in
MapAnnotation(coordinate: .init(latitude: course.location.latitude, longitude: course.location.longitude)) {
Image(systemName: "person")
.frame(width: 44, height: 44)
.onTapGesture(count: 1, perform: {
print("PRINT: \(course.name)")
selectedCourse = course
if selectedCourse != nil {
isShowSheet.toggle()
}
print("\(selectedCourse)")
})
}
}
.ignoresSafeArea()
} else {
Text("locating user location")
}
}
.fullScreenCover(isPresented: $isShowSheet, content: {
if let course = selectedCourse {
LocationInfoView(viewModel: LocationInfoViewModel(course: course))
.environment(\.showingSheet, self.$isShowSheet)
}
})
.alert(item: $viewModel.alertItem, content: { alertItem in
Alert(title: alertItem.title, message: alertItem.message, dismissButton: alertItem.dismissButton)
})
.onAppear {
setCurrentLocation()
}
}
}
解决方案
您应该使用其他签名.fullScreenCover
:
func fullScreenCover<Item, Content>(item: Binding<Item?>, onDismiss: (() -> Void)? = nil, @ViewBuilder content: @escaping (Item) -> Content)
这样 :
.fullScreenCover(item: $selectedCourse) { course in
// content
}
在您的示例中,item:
将是一个Course?
. 当您通过时Course
,fullScreenCover
就会出现;nil
它已经关闭了。
因此,您可以@Binding
在您的中使用 aLocationInfoView
来关闭fullScreenCover
. 但看起来您更喜欢使用EnvironmentKey
. 因此,您必须修改它:
private struct SelectedCourseKey: EnvironmentKey {
static let defaultValue: Binding<Course?> = .constant(nil)
}
extension EnvironmentValues {
var selectedCourse: Binding<Course?> {
get { self[SelectedCourseKey.self] }
set { self[SelectedCourseKey.self] = newValue }
}
}
在你的LocationInfoView
:
struct LocationInfoView: View {
@Environment(\.selectedCourse) var selectedCourse: Binding<Course?>
var viewModel: LocationInfoViewModel
var body: some View {
VStack {
Button("close") {
selectedCourse.wrappedValue = nil
}
// some code
}
}
}
最后,在你的CourseMapView
:
.fullScreenCover(item: $selectedCourse) { course in
if let course = course {
LocationInfoView(viewModel: LocationInfoViewModel(course: course))
.environment(\.selectedCourse, self.$selectedCourse)
}
}
推荐阅读
- sql-server - 在 SQLServer 中为该时间段内的付款添加 30 天、60 天和 90 天列
- docker - 无法在主机上访问 Dockerized Vue 的 localhost:8080(尽管 EXPOSE-ing 端口)
- android - 我已经使用 MediaStore.Audio.Media 从外部存储中读取了所有歌曲。但我无法提取歌曲的uri
- python - distplot如何计算kde曲线?
- javascript - 如何在 ionic 中使用自定义字体
- javascript - 如何从对象中删除字段
- javascript - Frida - Calling a specific method overload
- logging - 如何以编程方式启用登录 apache cxf jax-rs 客户端
- android - 如何在 Android 的 AlertDialog 中将最大高度设置为列表视图?
- firebase - 构建函数返回 null。颤振火力基地