【问题标题】:How to display view within a sheet programmatically in SwiftUI?如何在 SwiftUI 中以编程方式在工作表中显示视图?
【发布时间】:2019-11-24 02:41:16
【问题描述】:

我目前在 SwiftUI 中使用 Google Maps API,并试图在以编程方式点击标记 infoWindow 后显示一张工作表。

在我的应用程序的其他部分,我正在显示这样的工作表,这与我在这里尝试实现的目标相同,但以编程方式实现:

https://blog.kaltoun.cz/swiftui-presenting-modal-sheet/

现在我有一个函数可以在点击 infoWindow 时打印一条消息,但不知道如何使用该函数使 SwiftUI 视图出现在工作表中。

-

由于我使用的是 SwiftUI,因此我实现 Google Maps API 的方式与普通的 Swift 略有不同。 以下是我的 GMView.swift 文件的基础知识,该文件处理所有 google 地图内容。

import SwiftUI
import UIKit
import GoogleMaps
import GooglePlaces
import CoreLocation
import Foundation



struct GoogMapView: View {
    var body: some View {
        GoogMapControllerRepresentable()
    }
}


class GoogMapController: UIViewController, CLLocationManagerDelegate, GMSMapViewDelegate {
    var locationManager = CLLocationManager()
    var mapView: GMSMapView!
    let defaultLocation = CLLocation(latitude: 42.361145, longitude: -71.057083)
    var zoomLevel: Float = 15.0
    let marker : GMSMarker = GMSMarker()


    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager = CLLocationManager()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestAlwaysAuthorization()
        locationManager.distanceFilter = 50
        locationManager.startUpdatingLocation()
        locationManager.delegate = self

        let camera = GMSCameraPosition.camera(withLatitude: defaultLocation.coordinate.latitude, longitude: defaultLocation.coordinate.longitude, zoom: zoomLevel)
        mapView = GMSMapView.map(withFrame: view.bounds, camera: camera)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        mapView.isMyLocationEnabled = true
        mapView.setMinZoom(14, maxZoom: 20)
        mapView.settings.compassButton = true
        mapView.isMyLocationEnabled = true
        mapView.settings.myLocationButton = true
        mapView.settings.scrollGestures = true
        mapView.settings.zoomGestures = true
        mapView.settings.rotateGestures = true
        mapView.settings.tiltGestures = true
        mapView.isIndoorEnabled = false


        marker.position = CLLocationCoordinate2D(latitude: 42.361145, longitude: -71.057083)
        marker.title = "Boston"
        marker.snippet = "USA"
        marker.map = mapView

        // Add the map to the view, hide it until we've got a location update.
        view.addSubview(mapView)
//        mapView.isHidden = true

    }

    // Handle incoming location events.
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
      let location: CLLocation = locations.last!
      print("Location: \(location)")

      let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude, longitude: location.coordinate.longitude, zoom: zoomLevel)

      if mapView.isHidden {
        mapView.isHidden = false
        mapView.camera = camera
      } else {
        mapView.animate(to: camera)
      }

    }

    // Handle authorization for the location manager.
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
      switch status {
      case .restricted:
        print("Location access was restricted.")
      case .denied:
        print("User denied access to location.")
        // Display the map using the default location.
        mapView.isHidden = false
      case .notDetermined:
        print("Location status not determined.")
      case .authorizedAlways: fallthrough
      case .authorizedWhenInUse:
        print("Location status is OK.")
      }
    }

    // Handle location manager errors.
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
      locationManager.stopUpdatingLocation()
      print("Error: \(error)")
    }

}


struct GoogMapControllerRepresentable: UIViewControllerRepresentable {
    func makeUIViewController(context: UIViewControllerRepresentableContext<GMControllerRepresentable>) -> GMController {
        return GMController()
    }

    func updateUIViewController(_ uiViewController: GMController, context: UIViewControllerRepresentableContext<GMControllerRepresentable>) {

    }
}

这是我放在 GMView.swift 的 UIViewController (GMController) 中的函数,我试图用它来使视图出现在工作表中:

// Function to handle when a marker's infowindow is tapped
    func mapView(_ mapView: GMSMapView, didTapInfoWindowOf didTapInfoWindowOfMarker: GMSMarker) {
        print("You tapped a marker's infowindow!")
        return
    }

这是我想要显示的视图:

struct SortBy: View {
    var body: some View {

        VStack(alignment: .leading) {
            Text("Sort By")
                .font(.title)
                .fontWeight(.black)
                .padding(.trailing, 6)
            Rectangle()
            .fill(Color.blue)
            .frame(width: 200, height: 200)
        }

    }
}

有谁知道我如何获得上面的函数以使 SwiftUI 视图出现在工作表中?

【问题讨论】:

  • 在你的 SwiftUI 代码中添加一个 @EnvironmentObject 变量并检查它是否为真。如果是真的显示一张纸。在您的 MapView didSelect 中将此变量设置为 true,在关闭工作表时在您的 SwiftUI 代码中将其设置为 false。

标签: google-maps swiftui google-maps-sdk-ios infowindow gmsmapview


【解决方案1】:

【讨论】:

  • 这类似于我上面引用的链接,用于使其他模态出现。但是,如果我将此代码添加到我的视图.sheet(isPresented: self.$show_modal) { ModalView() },我将如何使 UIViewController 中的函数切换视图中的变量以显示模式?
【解决方案2】:

你需要:

  1. 在您的UIViewControllerRepresentable 中,添加一个State 对象,比如说@State var showModal = false
  2. 在您的父视图中,使用.sheet(isPresented: $showModal) { CONTENT_VIEW(showModal: $showModal) }
  3. 在您的UIViewControllerRepresentable 中,还为showModal 添加一个绑定。
  4. 在您的UIViewControllerRepresentable 中,使用Coordinator 设置您的UIViewControllerGMSMapViewDelegate
  5. 在您的 UIViewController 中,现在您可以通过 owner.showModal 访问绑定

希望对您有所帮助。祝你好运。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-19
    • 1970-01-01
    • 2011-12-09
    • 2019-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-06
    相关资源
    最近更新 更多