Lan*_*ria 3 mkannotation ios swift calloutview
我的地图视图有一个自定义注释。我最初使用一些数据设置了坐标、标题(例如“第一个标题”)、副标题(例如“第一个地址”)、userId 和距离(例如 0 米)属性。我将其添加到 mapView 和数组中以供以后使用。一切正常,它显示在地图视图上,我按下它,标注显示初始数据。
后来我得知该标注的位置已更改。我循环遍历数组并使用坐标、标题(例如“新标题”)、副标题(例如“新地址”)和距离(例如 100 米)属性的新数据更新标注。我还将标注从原始位置动画化到新位置。动画工作正常,标注从 A 点移动到 B 点。
问题是,当我点击注释时,旧数据会显示在标注上,而不是新数据。
我过去常calloutAccessoryControlTapped推新的VC。当我在那里放置断点时,自定义引脚具有所有新数据。该错误似乎是在标注时发生的。
我该如何解决?
我不想清除地图视图中的所有注释,所以这不是一个选项。我致电mapView.removeAnnotation(customPin)并mapView.addAnnotation(customPin)解决了该图钉的问题,但是当图钉被移除并添加回地图时,会出现闪烁,然后当它动画到新位置时,它看起来不稳定。
自定义注释
class CustomPin: NSObject, MKAnnotation {
@objc dynamic var coordinate: CLLocationCoordinate2D
var title: String?
var subtitle: String?
var userId: String?
var distance: CLLocationDistance?
init(coordinate: CLLocationCoordinate2D, title: String, subtitle: String, userId: String, distance: CLLocationDistance?) {
self.coordinate = coordinate
self.title = title
self.subtitle = subtitle
self.userId = userId
self.distance = distance
super.init()
}
}
Run Code Online (Sandbox Code Playgroud)
第一次使用初始数据设置注释
firstFunctionThatGetsTheInitialLocation(origLat, origLon) {
let firstCoordinate = CLLocationCoordinate2DMake(origLat, origLon)
let distanceInMeters: CLLocationDistance = self.center.distance(from: anotherUsersLocation)
let customPin = CustomPin(coordinate: firstCoordinate, title: "first title", subtitle: "first address", userId: "12345", distance: distance)
DispatchQueue.main.async { [weak self] in
self?.mapView.addAnnotation(customPin)
self?.arrOfPins.append(customPin)
}
}
Run Code Online (Sandbox Code Playgroud)
第二次使用新数据设置注释
secondFunctionThatGetsTheNewLocation(newCoordinate: CLLocationCoordinate2D, newDistance: CLLocationDistance) {
for pin in customPins {
pin.title = "second title" // ** updates but the callout doesn't reflect it
pin.subTitle = "second address" // ** updates but the callout doesn't reflect it
pin.distance = newDistance // ** updates but the callout doesn't reflect it
// calling these gives me the new data but the annotation blinks and moves really fast to it's new location
// mapView.removeAnnotation(pin)
// mapView.addAnnotation(pin)
UIView.animate(withDuration: 1) {
pin.coordinate = newCoordinate // this updates and animates to the new location with no problem
}
}
}
Run Code Online (Sandbox Code Playgroud)
MapView视图用于注释
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isKind(of: MKUserLocation.self) { return nil }
guard let annotation = annotation as? CustomPin else { return nil }
let reuseIdentifier = "CustomPin"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
annotationView?.canShowCallout = true
annotationView?.calloutOffset = CGPoint(x: -5, y: 5)
annotationView?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
annotationView?.image = UIImage(named: "chevronImage")
} else {
annotationView?.annotation = annotation
}
annotationView?.detailCalloutAccessoryView = nil
annotationView?.detailCalloutAccessoryView = createCallOutWithDataFrom(customPin: annotation)
return annotationView
}
Run Code Online (Sandbox Code Playgroud)
为标注创建 UIView
func createCallOutWithDataFrom(customPin: CustomPin) -> UIView {
let titleText = customPin.title
let subTitleText = customPin.subTitle
let distanceText = subTitle.distance // gets converted to a string
// 1. create a UIView
// 2. create some labels and add the text from the title, subTitle, and distance and add them as subViews to the UIView
// 3. return the UIView
}
Run Code Online (Sandbox Code Playgroud)
有几个问题:
\n\n您需要@objc dynamic对要观察的任何属性使用限定符。标准标注对和执行键值观察(KVO) 。(注释视图观察到的更改。)titlesubtitlecoordinate
如果你想观察userid和distance,你也必须做出这些@objc dynamic。请注意,您\xe2\x80\x99ll 必须使其distance成为非可选才能使其可观察:
var distance: CLLocationDistance\nRun Code Online (Sandbox Code Playgroud)\n\n所以:
\n\nclass CustomAnnotation: NSObject, MKAnnotation {\n // standard MKAnnotation properties\n\n @objc dynamic var coordinate: CLLocationCoordinate2D\n @objc dynamic var title: String?\n @objc dynamic var subtitle: String?\n\n // additional custom properties\n\n @objc dynamic var userId: String\n @objc dynamic var distance: CLLocationDistance\n\n init(coordinate: CLLocationCoordinate2D, title: String, subtitle: String, userId: String, distance: CLLocationDistance) {\n self.userId = userId\n self.distance = distance\n self.coordinate = coordinate\n self.title = title\n self.subtitle = subtitle\n\n super.init()\n }\n}\nRun Code Online (Sandbox Code Playgroud)就像我说的,标准标注观察title和subtitle。虽然您必须使注释属性可观察,但如果您要构建自己的detailCalloutAccessoryView,则您将必须执行自己的 KVO:
class CustomAnnotationView: MKMarkerAnnotationView {\n private let customClusteringIdentifier = "..."\n\n override init(annotation: MKAnnotation?, reuseIdentifier: String?) {\n super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)\n canShowCallout = true\n detailCalloutAccessoryView = createCallOutWithDataFrom(customAnnotation: annotation as? CustomAnnotation)\n clusteringIdentifier = customClusteringIdentifier\n }\n\n required init?(coder aDecoder: NSCoder) {\n fatalError("init(coder:) has not been implemented")\n }\n\n deinit {\n removeAnyObservers()\n }\n\n override var annotation: MKAnnotation? {\n didSet {\n removeAnyObservers()\n clusteringIdentifier = customClusteringIdentifier\n if let customAnnotation = annotation as? CustomAnnotation {\n updateAndAddObservers(for: customAnnotation)\n }\n }\n }\n\n private var subtitleObserver: NSKeyValueObservation?\n private var userObserver: NSKeyValueObservation?\n private var distanceObserver: NSKeyValueObservation?\n\n private let subtitleLabel: UILabel = {\n let label = UILabel()\n label.translatesAutoresizingMaskIntoConstraints = false\n return label\n }()\n\n private let userLabel: UILabel = {\n let label = UILabel()\n label.translatesAutoresizingMaskIntoConstraints = false\n return label\n }()\n\n private let distanceLabel: UILabel = {\n let label = UILabel()\n label.translatesAutoresizingMaskIntoConstraints = false\n return label\n }()\n}\n\nprivate extension CustomAnnotationView {\n func updateAndAddObservers(for customAnnotation: CustomAnnotation) {\n subtitleLabel.text = customAnnotation.subtitle\n subtitleObserver = customAnnotation.observe(\\.subtitle) { [weak self] customAnnotation, _ in\n self?.subtitleLabel.text = customAnnotation.subtitle\n }\n\n userLabel.text = customAnnotation.userId\n userObserver = customAnnotation.observe(\\.userId) { [weak self] customAnnotation, _ in\n self?.userLabel.text = customAnnotation.userId\n }\n\n distanceLabel.text = "\\(customAnnotation.distance) meters"\n distanceObserver = customAnnotation.observe(\\.distance) { [weak self] customAnnotation, _ in\n self?.distanceLabel.text = "\\(customAnnotation.distance) meters"\n }\n }\n\n func removeAnyObservers() {\n subtitleObserver = nil\n userObserver = nil\n distanceObserver = nil\n }\n\n func createCallOutWithDataFrom(customAnnotation: CustomAnnotation?) -> UIView {\n let view = UIView()\n view.translatesAutoresizingMaskIntoConstraints = false\n view.addSubview(subtitleLabel)\n view.addSubview(userLabel)\n view.addSubview(distanceLabel)\n\n NSLayoutConstraint.activate([\n subtitleLabel.topAnchor.constraint(equalTo: view.topAnchor),\n subtitleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor),\n subtitleLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor),\n subtitleLabel.bottomAnchor.constraint(equalTo: userLabel.topAnchor),\n\n userLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor),\n userLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor),\n userLabel.bottomAnchor.constraint(equalTo: distanceLabel.topAnchor),\n\n distanceLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor),\n distanceLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor),\n distanceLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor)\n ])\n\n if let customAnnotation = customAnnotation {\n updateAndAddObservers(for: customAnnotation)\n }\n\n return view\n }\n}\nRun Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
1913 次 |
| 最近记录: |