你能从 SwiftUI 中的 MapKit 数据库中获取纬度和经度吗
Posted
技术标签:
【中文标题】你能从 SwiftUI 中的 MapKit 数据库中获取纬度和经度吗【英文标题】:Can You Get Latitude and Longitude From A Database for MapKit in SwiftUI 【发布时间】:2021-10-08 06:23:49 【问题描述】:我正在处理一个 SwiftUI 项目,并希望将地图放置在使用存储在 Firestore 中的坐标的视图中。 Apple 在 SwiftUI 中的 MapKit 示例在 @State 属性中使用静态纬度和经度参数,然后将该属性绑定到 Map() 视图。
struct BusinessMapView: View
@State private var region: MKCoordinateRegion =
var mapCoordinates = CLLocationCoordinate2D(latitude: 44.621754, longitude: -66.475873)
var mapZoomLevel = MKCoordinateSpan(latitudeDelta: 5.00, longitudeDelta: 5.00)
var mapRegion = MKCoordinateRegion(center: mapCoordinates, span: mapZoomLevel)
return mapRegion
()
var body: some View
Map(coordinateRegion: $region)
我想要做的是以下内容,但显然这是不允许的,因为您无法访问另一个属性中的其他属性。
struct BusinessMapView: View
@ObservedObject var businessAddressRowViewModel: BusinessAddressRowViewModel
@State private var region: MKCoordinateRegion =
var mapCoordinates = CLLocationCoordinate2D(latitude: businessAddressRowViewModel.businessAddress.latitude, longitude: businessAddressRowViewModel.businessAddress.longitude)
var mapZoomLevel = MKCoordinateSpan(latitudeDelta: 5.00, longitudeDelta: 5.00)
var mapRegion = MKCoordinateRegion(center: mapCoordinates, span: mapZoomLevel)
return mapRegion
()
var body: some View
Map(coordinateRegion: $region)
所以我的问题是,有没有办法从数据库中为 SwiftUI 中的 Map() 设置坐标,还是唯一的选择是使用静态值作为纬度和经度?
为更多信息添加了编辑
class BusinessAddressRowViewModel: ObservableObject, Identifiable
// Properties
var id: String = ""
public static let shared = BusinessAddressRowViewModel()
// Published Properties
@Published var businessAddress: BusinessAddress
// Combine Cancellable
private var cancellables = Set<AnyCancellable>()
// Initializer
init(businessAddress: BusinessAddress)
self.businessAddress = businessAddress
self.startCombine()
// Starting Combine
func startCombine()
// Get Bank Account
$businessAddress
.receive(on: RunLoop.main)
.compactMap businessAddress in
businessAddress.id
.assign(to: \.id, on: self)
.store(in: &cancellables)
共享属性给出一个错误,说明缺少参数 businessAddress。
数据来自此处的 Firebase Firestore。
class BusinessAddressRepository: ObservableObject
let db = Firestore.firestore()
private var snapshotListener: ListenerRegistration?
@Published var businessAddresses = [BusinessAddress]()
init()
startSnapshotListener()
func startSnapshotListener()
// Get the currentUserUid
guard let currentUserId = Auth.auth().currentUser else
return
if snapshotListener == nil
// Add a SnapshotListener to the BusinessAddress Collection.
self.snapshotListener = db.collection(FirestoreCollection.users).document(currentUserId.uid).collection(FirestoreCollection.businessAddresses).addSnapshotListener (querySnapshot, error) in
// Check to see if an error occured and print it. IMPLEMENT ERROR HANDLING LATER
if let error = error
print("Error getting documents: \(error)")
else
print("BusinessAddressRepository - snapshotListener called")
// Check to make sure the Collection contains Documents
guard let documents = querySnapshot?.documents else
print("No Business Addresses.")
return
// Documents exist.
self.businessAddresses = documents.compactMap businessAddress in
do
return try businessAddress.data(as: BusinessAddress.self)
catch
print(error)
return nil
func stopSnapshotListener()
if snapshotListener != nil
snapshotListener?.remove()
snapshotListener = nil
数据正在从 BusinessAddressViewModel 传递到 BusinessAddressRowViewModel。 BusinessAddressView 包含创建所有行的列表。
class BusinessAddressViewModel: ObservableObject
var businessAddressRepository: BusinessAddressRepository
// Published Properties
@Published var businessAddressRowViewModels = [BusinessAddressRowViewModel]()
// Combine Cancellable
private var cancellables = Set<AnyCancellable>()
// Intitalizer
init(businessAddressRepository: BusinessAddressRepository)
self.businessAddressRepository = businessAddressRepository
self.startCombine()
// Starting Combine - Filter results for business addresses created by the current user only.
func startCombine()
businessAddressRepository
.$businessAddresses
.receive(on: RunLoop.main)
.map businessAddress in
businessAddress
.map businessAddress in
BusinessAddressRowViewModel(businessAddress: businessAddress)
.assign(to: \.businessAddressRowViewModels, on: self)
.store(in: &cancellables)
【问题讨论】:
第二块上面的代码无法编译。它抛出一个错误。由于 region 引用了 businessCoordinates,所以这是不允许的。我的问题是如何将区域与数据库中的数据一起使用,因为您无法引用其他属性,例如 businessCoordinates。 【参考方案1】:这里有一个初始化问题,与 Map() 无关。您正在尝试在初始化程序中使用 businessCoordinates
实例化的 ObservedObject
变量,并且我确信会收到 Cannot use instance member 'businessCoordinates' within property initializer; property initializers run before 'self' is available
错误。
如果您在视图中的任何地方都不需要“businessCoordinates”,除了数据,我建议这样做:
class BusinessCoordinates: ObservableObject
public static let shared = BusinessCoordinates()
...
这会给你一个Singleton
,你可以随意使用。然后你像这样使用它:
struct BusinessMapView: View
@State private var region: MKCoordinateRegion
init()
let mapCoordinates = CLLocationCoordinate2D(latitude: BusinessCoordinates.shared.latitude, longitude: BusinessCoordinates.shared.longitude)
var mapZoomLevel = MKCoordinateSpan(latitudeDelta: 5.00, longitudeDelta: 5.00)
_region = State(initialValue: MKCoordinateRegion(center: mapCoordinates, span: mapZoomLevel))
var body: some View
Map(coordinateRegion: $region)
【讨论】:
虽然我喜欢这种方法,但我不确定它是否适用于我的应用程序。我已经更新了上面的问题以显示当前的 BusinessCoordinates 文件。由于该文件是行视图的视图模型,因此我正在为 VM 提供业务地址。这意味着我必须使用公司地址启动共享财产。我不知道这怎么可能。 您将其放入BusinessAddressRowViewModel
,但在MapView
中您使用BusinessCoordinates
作为ObservedObject
。这是哪里来的?
我很抱歉造成混乱。我在原始帖子中重命名了文件,尝试简化事情。我已更改 ObservedObject 的命名以匹配文件名。
数据从何而来?离开你的地图视图,你如何将数据输入BusinessAddressRowViewModel
?在您实例化 BusinessAddressRowViewModel
之前,是什么保存了这些数据?
我添加了从 Firebase Firestore 中提取数据的存储库文件和创建 BusinessAddressRowViewModels 的 BusinessAddressViewModel。以上是关于你能从 SwiftUI 中的 MapKit 数据库中获取纬度和经度吗的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI:如何在 MapKit 中自定义地理区域的位置?
在 swiftUI 2 中向 MapKit 添加 MapMarker