swiftui - 你能从 SwiftUI 中的 MapKit 数据库中获取纬度和经度吗
问题描述
我正在开发一个 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)
}
}
解决方案
你这里有一个初始化问题,与 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)
}
}
推荐阅读
- symfony - Sonata 管理员列表字段模板被忽略
- jmeter - 错误:UnicodeDecodeError:'charmap' - Taurus
- reactjs - 反应项目 WAR 文件
- android - 库 com.google.firebase:firebase-analytics 正在被其他各种库请求
- c++11 - 移动构造函数注释未打印
- css - flexbox 项目的图像和文本与绝对定位的 div 重叠(工具提示)
- oracle-cloud-infrastructure - oci java sdk 通过代理
- c# - Unity 2018 C# - Fbx 使用输入运行动画缩放?
- javascript - 结合 ReactJS + Marzipano 时出现白屏?
- service-worker - 缓存在相对路径下的缓存存储中的项目