ZStack中Map组件出现2个错误,getAnnotations函数无错,求先解决Map错误
问题与解决方法
问题描述
我创建了函数getAnnotations,调用和定义都没报错,但Map组件出现两个错误:
Initializer 'init(coordinateRegion:interactionModes:showsUserLocation:userTrackingMode:annotationItems:annotationContent:)' requires that 'MKPointAnnotation.Type.Element' conform to 'Identifiable'
以及
Type 'MKPointAnnotation.Type' cannot conform to 'RandomAccessCollection'
getAnnotations函数代码:
func getAnnotations(completion: @escaping (_ annotations: [MKPointAnnotation]?) -> Void) { let db = Firestore.firestore() db.collection("annotations").addSnapshotListener { (querySnapshot, err) in guard let snapshot = querySnapshot else { if let err = err { print(err) } completion(nil) // return nil if error return } guard !snapshot.isEmpty else { completion([]) // return empty if no documents return } var annotations = [MKPointAnnotation]() for doc in snapshot.documents { if let lat = doc.get("lat") as? String, let lon = doc.get("long") as? String, let latitude = Double(lat), let longitude = Double(lon) { let coord = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) let annotation = MKPointAnnotation() annotation.coordinate = coord annotations.append(annotation) } } completion(annotations) // return array } }
视图代码:
ZStack (alignment: .bottom) { Map(coordinateRegion: $viewModel.region, showsUserLocation: true, annotationItems: MKPointAnnotation) { annotations in MapAnnotation(coordinate: annotations.coordinate) { Circle() } } .ignoresSafeArea() .tint(.pink) LocationButton(.currentLocation) { viewModel.requestAllowOnceLocationPermission() } .foregroundColor(.white) .cornerRadius(8) .labelStyle(.iconOnly) .symbolVariant(.fill) .tint(.pink) .padding(.bottom) .padding(.trailing, 300) } .onAppear { getAnnotations({ (annotations) in if let annotations = annotations { print(annotations) } }) }
我尝试把函数改成同步的,还是报这两个错,想先解决错误验证getAnnotations是否正常工作。
解决步骤
1. 让MKPointAnnotation遵守Identifiable协议
SwiftUI的Map组件要求标注项必须是可识别的,给MKPointAnnotation添加扩展:
extension MKPointAnnotation: Identifiable { public var id: UUID { // 用坐标生成唯一ID,避免重复标注出现识别冲突 UUID(uuidString: "\(coordinate.latitude)-\(coordinate.longitude)") ?? UUID() } }
2. 在视图中添加存储标注的状态变量
需要用数组存储从Firestore获取到的标注实例,不能直接传类型:
// 在视图结构体内部添加 @State private var mapAnnotations: [MKPointAnnotation] = []
3. 修改onAppear逻辑,将获取到的标注赋值给状态变量
.onAppear { getAnnotations({ (annotations) in if let annotations = annotations { self.mapAnnotations = annotations print(annotations) } }) }
4. 修正Map组件的annotationItems参数
把原来的MKPointAnnotation替换为我们定义的状态数组mapAnnotations:
Map(coordinateRegion: $viewModel.region, showsUserLocation: true, annotationItems: mapAnnotations) { annotation in MapAnnotation(coordinate: annotation.coordinate) { Circle() } }
错误原因说明
- 「无法符合
RandomAccessCollection」错误:你给annotationItems传的是MKPointAnnotation类型本身,而不是一个可遍历的集合实例(比如数组),Map组件需要的是能被遍历的标注集合,因此报错。 - 「需要符合
Identifiable」错误:SwiftUI的标注渲染逻辑依赖元素的唯一标识,MKPointAnnotation默认不遵守Identifiable协议,所以需要扩展实现该协议。
内容的提问来源于stack exchange,提问作者user19620292
相关产品推荐
相关产品推荐

