首页 > 解决方案 > 如何将数据从地图注释传输到全屏封面弹出窗口

问题描述

用户单击 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()
  }
 } 
}

标签: swiftuimapkitdata-transfer

解决方案


您应该使用其他签名.fullScreenCover

func fullScreenCover<Item, Content>(item: Binding<Item?>, onDismiss: (() -> Void)? = nil, @ViewBuilder content: @escaping (Item) -> Content)

这样 :

.fullScreenCover(item: $selectedCourse) { course in
       // content
}

在您的示例中,item:将是一个Course?. 当您通过时CoursefullScreenCover就会出现;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)
       }
   }

推荐阅读