由于 MKPointAnnotation 上无法识别的选择器而导致崩溃
Crash due to unrecognised selector on MKPointAnnotation
我已经为 MKMapView 完成了聚类。
class BaseMKPointAnnotation: MKPointAnnotation {
var index: Int!
}
class ClusteredAnnotationView: MKMarkerAnnotationView {
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
// Enable clustering by just setting the clusteringIdentifier
clusteringIdentifier = "AnnotationView"
// clusteringIdentifier = nil
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepareForDisplay() {
super.prepareForDisplay()
displayPriority = .defaultHigh
glyphImage = Images.annotationIcon
}
}
extension MKMapView {
func animateToPoint(_ coordinate: CLLocationCoordinate2D, animated: Bool) {
let coordinateRegion = MKCoordinateRegion(center: coordinate, latitudinalMeters: 250.0, longitudinalMeters: 250.0)
self.setRegion(coordinateRegion, animated: animated)
}
}
所以我有我的 ViewController。它在集合视图调用 mapViewAnimateTo
时崩溃。虽然它不经常崩溃,但它确实会崩溃。
class ViewController: UIViewController {
// Method that will add annotations to the mapView.
private func addAnnotation(_ i: Int, _ coordinate: CLLocationCoordinate2D) {
let annotation = BaseMKPointAnnotation()
annotation.index = i // Index to differentiate the annotation.
annotation.coordinate = coordinate
mapView.addAnnotation(annotation)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
var annotationView = self.mapView.dequeueReusableAnnotationView(withIdentifier: "Pin")
if annotationView == nil {
annotationView = ClusteredAnnotationView(annotation: annotation, reuseIdentifier: "Pin")
} else {
annotationView?.annotation = annotation
}
return annotationView
}
// This method is called when horizontal collection view stops scrolling.
func mapViewAnimateTo(_ index: Int) {
// Gets the array of points
let point = presenter.getCollectedPoints(index).coordinates
// coordinate to animate.
let coordinate = CLLocationCoordinate2D(latitude: point[0].latitude, longitude: point[0].longitude)
// animates to the coordinate
/*********** Sometimes it crashes here. ***********/
mapView.animateToPoint(coordinate, animated: true)
for annotation in mapView.annotations {
if annotation.coordinate.latitude == coordinate.latitude && annotation.coordinate.longitude == coordinate.longitude {
// mark the annotation as selected.
/*********** Sometimes it crashes here. ***********/
mapView.selectAnnotation(annotation, animated: true)
}
}
}
}
它崩溃并出现以下报告,我该如何解决这个崩溃。在这里,我附上了崩溃的图像
2019-04-17 16:17:21.033478+0530 Demo App[13618:213851] -[Demo_App.BaseMKPointAnnotation memberAnnotations]: unrecognized selector sent to instance 0x6000007e2da0
2019-04-17 16:17:21.042907+0530 Demo App[13618:213851] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Demo_App.BaseMKPointAnnotation memberAnnotations]: unrecognized selector sent to instance 0x6000007e2da0'
*** First throw call stack:
(
0 CoreFoundation 0x0000000115c0a6fb __exceptionPreprocess + 331
1 libobjc.A.dylib 0x00000001151aeac5 objc_exception_throw + 48
2 CoreFoundation 0x0000000115c28ab4 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x0000000115c0f443 ___forwarding___ + 1443
4 CoreFoundation 0x0000000115c11238 _CF_forwarding_prep_0 + 120
5 MapKit 0x0000000116577298 -[MKMapView annotationContainer:requestAddingClusterForAnnotationViews:] + 168
6 MapKit 0x0000000116703e7c -[MKAnnotationContainerView _updateClusterableAnnotationViews:withID:] + 461
7 CoreFoundation 0x0000000115c7a9c2 -[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] + 226
8 MapKit 0x00000001166ff3fc -[MKAnnotationContainerView updateAnnotationViewsForReason:] + 282
9 MapKit 0x0000000116702cbc -[MKAnnotationContainerView finishAddingAnnotationViews] + 29
10 MapKit 0x000000011657f59f -[MKMapView annotationManager:didAddAnnotationRepresentations:] + 53
11 MapKit 0x000000011663d24e -[MKAnnotationManager updateVisibleAnnotations] + 1660
12 MapKit 0x000000011656e238 -[MKMapView _didChangeRegionMidstream:] + 208
13 MapKit 0x00000001165734a2 -[MKMapView mapLayer:didChangeRegionAnimated:] + 67
14 VectorKit 0x000000012f00ae54 -[VKMapView map:didChangeRegionAnimated:] + 122
15 VectorKit 0x000000012f089f6b __86-[VKMapCameraController _animateToPosition:pitch:yaw:duration:timingCurve:completion:]_block_invoke.227 + 75
16 VectorKit 0x000000012f042747 -[VKAnimation stopAnimation:] + 106
17 VectorKit 0x000000012f042b4c -[VKTimedAnimation stopAnimation:] + 44
18 VectorKit 0x000000012f042c2e -[VKTimedAnimation onTimerFired:] + 47
19 VectorKit 0x000000012efb0b24 _ZN2md16AnimationManager12onTimerFiredEd + 208
20 VectorKit 0x000000012efb1b60 _ZN2md27InteractiveAnimationManager12onTimerFiredEd + 14
21 VectorKit 0x000000012f26246c _ZN2md9MapEngine11layoutSceneEdb + 96
22 VectorKit 0x000000012f2623f6 -[_MapEngineRenderQueueSource renderQueueForTimestamp:] + 27
23 VectorKit 0x000000012f3212e7 -[MDDisplayLayer drawToTexture:withTimestamp:completionHandler:prepareHandler:] + 139
24 VectorKit 0x000000012f46224f __33-[GGLOpenGLESLayer onTimerFired:]_block_invoke + 87
25 VectorKit 0x000000012f469049 _ZN3ggl10OESContext17performWhileBoundEU13block_pointerFvvE + 163
26 VectorKit 0x000000012f462009 -[GGLOpenGLESLayer onTimerFired:] + 106
27 VectorKit 0x000000012f2642d3 _ZN2md9MapEngine11renderSceneEdNSt3__18functionIFvvEEE + 93
28 VectorKit 0x000000012f263f34 _ZN2md9MapEngine18onRenderTimerFiredEd + 188
29 VectorKit 0x000000012f464c4c _ZN3ggl11DisplayLink12onTimerFiredEd + 32
30 VectorKit 0x000000012f464b1b -[_GGLDisplayLinkTarget displayLinkFired:] + 81
31 QuartzCore 0x0000000112339d97 _ZN2CA7Display11DisplayLink14dispatch_itemsEyyy + 663
32 QuartzCore 0x00000001124084a2 _ZL22display_timer_callbackP12__CFMachPortPvlS1_ + 297
33 CoreFoundation 0x0000000115b46096 __CFMachPortPerform + 150
34 CoreFoundation 0x0000000115b72419 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
35 CoreFoundation 0x0000000115b71a7b __CFRunLoopDoSource1 + 459
36 CoreFoundation 0x0000000115b6c00a __CFRunLoopRun + 2490
37 CoreFoundation 0x0000000115b6b302 CFRunLoopRunSpecific + 626
38 GraphicsServices 0x00000001197dc2fe GSEventRunModal + 65
39 UIKitCore 0x0000000120226ba2 UIApplicationMain + 140
40 TOSCollect Live 0x000000010f16200b main + 75
41 libdyld.dylib 0x0000000117743541 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
当我选择在地图上不可见的注释时,问题出现了。我很乱。
我解决了这个问题,方法是先缩放到该位置,然后将注释 属性 设置为选中状态。
所以我更新了mapViewAnimateTo
方法。
func mapViewAnimateTo(_ index: Int) {
print("MapView scrolling to index \(index)")
let point = presenter.getCollectedPoints(index).coordinates
let coordinate = CLLocationCoordinate2D(latitude: point[0].latitude, longitude: point[0].longitude)
CATransaction.begin()
CATransaction.setCompletionBlock({
// 2. Upon completion of zooming, marks the first annotation found at respective coordinate as selected.
if let annotation = self.mapView.annotations.filter ({ [=10=].coordinate.latitude == coordinate.latitude && [=10=].coordinate.longitude == coordinate.longitude }).first {
self.mapView.selectAnnotation(annotation, animated: true)
}
})
// 1. Zooms to the respective coordinate.
mapView.animateToPoint(coordinate, animated: true)
CATransaction.commit()
}
甚至将区域的距离更新为 10 米。
extension MKMapView {
func animateToPoint(_ coordinate: CLLocationCoordinate2D, animated: Bool) {
let coordinateRegion = MKCoordinateRegion(center: coordinate, latitudinalMeters: 10, longitudinalMeters: 10)
self.setRegion(coordinateRegion, animated: animated)
}
}
我已经为 MKMapView 完成了聚类。
class BaseMKPointAnnotation: MKPointAnnotation {
var index: Int!
}
class ClusteredAnnotationView: MKMarkerAnnotationView {
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
// Enable clustering by just setting the clusteringIdentifier
clusteringIdentifier = "AnnotationView"
// clusteringIdentifier = nil
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepareForDisplay() {
super.prepareForDisplay()
displayPriority = .defaultHigh
glyphImage = Images.annotationIcon
}
}
extension MKMapView {
func animateToPoint(_ coordinate: CLLocationCoordinate2D, animated: Bool) {
let coordinateRegion = MKCoordinateRegion(center: coordinate, latitudinalMeters: 250.0, longitudinalMeters: 250.0)
self.setRegion(coordinateRegion, animated: animated)
}
}
所以我有我的 ViewController。它在集合视图调用 mapViewAnimateTo
时崩溃。虽然它不经常崩溃,但它确实会崩溃。
class ViewController: UIViewController {
// Method that will add annotations to the mapView.
private func addAnnotation(_ i: Int, _ coordinate: CLLocationCoordinate2D) {
let annotation = BaseMKPointAnnotation()
annotation.index = i // Index to differentiate the annotation.
annotation.coordinate = coordinate
mapView.addAnnotation(annotation)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
var annotationView = self.mapView.dequeueReusableAnnotationView(withIdentifier: "Pin")
if annotationView == nil {
annotationView = ClusteredAnnotationView(annotation: annotation, reuseIdentifier: "Pin")
} else {
annotationView?.annotation = annotation
}
return annotationView
}
// This method is called when horizontal collection view stops scrolling.
func mapViewAnimateTo(_ index: Int) {
// Gets the array of points
let point = presenter.getCollectedPoints(index).coordinates
// coordinate to animate.
let coordinate = CLLocationCoordinate2D(latitude: point[0].latitude, longitude: point[0].longitude)
// animates to the coordinate
/*********** Sometimes it crashes here. ***********/
mapView.animateToPoint(coordinate, animated: true)
for annotation in mapView.annotations {
if annotation.coordinate.latitude == coordinate.latitude && annotation.coordinate.longitude == coordinate.longitude {
// mark the annotation as selected.
/*********** Sometimes it crashes here. ***********/
mapView.selectAnnotation(annotation, animated: true)
}
}
}
}
它崩溃并出现以下报告,我该如何解决这个崩溃。在这里,我附上了崩溃的图像
2019-04-17 16:17:21.033478+0530 Demo App[13618:213851] -[Demo_App.BaseMKPointAnnotation memberAnnotations]: unrecognized selector sent to instance 0x6000007e2da0
2019-04-17 16:17:21.042907+0530 Demo App[13618:213851] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Demo_App.BaseMKPointAnnotation memberAnnotations]: unrecognized selector sent to instance 0x6000007e2da0'
*** First throw call stack:
(
0 CoreFoundation 0x0000000115c0a6fb __exceptionPreprocess + 331
1 libobjc.A.dylib 0x00000001151aeac5 objc_exception_throw + 48
2 CoreFoundation 0x0000000115c28ab4 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x0000000115c0f443 ___forwarding___ + 1443
4 CoreFoundation 0x0000000115c11238 _CF_forwarding_prep_0 + 120
5 MapKit 0x0000000116577298 -[MKMapView annotationContainer:requestAddingClusterForAnnotationViews:] + 168
6 MapKit 0x0000000116703e7c -[MKAnnotationContainerView _updateClusterableAnnotationViews:withID:] + 461
7 CoreFoundation 0x0000000115c7a9c2 -[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] + 226
8 MapKit 0x00000001166ff3fc -[MKAnnotationContainerView updateAnnotationViewsForReason:] + 282
9 MapKit 0x0000000116702cbc -[MKAnnotationContainerView finishAddingAnnotationViews] + 29
10 MapKit 0x000000011657f59f -[MKMapView annotationManager:didAddAnnotationRepresentations:] + 53
11 MapKit 0x000000011663d24e -[MKAnnotationManager updateVisibleAnnotations] + 1660
12 MapKit 0x000000011656e238 -[MKMapView _didChangeRegionMidstream:] + 208
13 MapKit 0x00000001165734a2 -[MKMapView mapLayer:didChangeRegionAnimated:] + 67
14 VectorKit 0x000000012f00ae54 -[VKMapView map:didChangeRegionAnimated:] + 122
15 VectorKit 0x000000012f089f6b __86-[VKMapCameraController _animateToPosition:pitch:yaw:duration:timingCurve:completion:]_block_invoke.227 + 75
16 VectorKit 0x000000012f042747 -[VKAnimation stopAnimation:] + 106
17 VectorKit 0x000000012f042b4c -[VKTimedAnimation stopAnimation:] + 44
18 VectorKit 0x000000012f042c2e -[VKTimedAnimation onTimerFired:] + 47
19 VectorKit 0x000000012efb0b24 _ZN2md16AnimationManager12onTimerFiredEd + 208
20 VectorKit 0x000000012efb1b60 _ZN2md27InteractiveAnimationManager12onTimerFiredEd + 14
21 VectorKit 0x000000012f26246c _ZN2md9MapEngine11layoutSceneEdb + 96
22 VectorKit 0x000000012f2623f6 -[_MapEngineRenderQueueSource renderQueueForTimestamp:] + 27
23 VectorKit 0x000000012f3212e7 -[MDDisplayLayer drawToTexture:withTimestamp:completionHandler:prepareHandler:] + 139
24 VectorKit 0x000000012f46224f __33-[GGLOpenGLESLayer onTimerFired:]_block_invoke + 87
25 VectorKit 0x000000012f469049 _ZN3ggl10OESContext17performWhileBoundEU13block_pointerFvvE + 163
26 VectorKit 0x000000012f462009 -[GGLOpenGLESLayer onTimerFired:] + 106
27 VectorKit 0x000000012f2642d3 _ZN2md9MapEngine11renderSceneEdNSt3__18functionIFvvEEE + 93
28 VectorKit 0x000000012f263f34 _ZN2md9MapEngine18onRenderTimerFiredEd + 188
29 VectorKit 0x000000012f464c4c _ZN3ggl11DisplayLink12onTimerFiredEd + 32
30 VectorKit 0x000000012f464b1b -[_GGLDisplayLinkTarget displayLinkFired:] + 81
31 QuartzCore 0x0000000112339d97 _ZN2CA7Display11DisplayLink14dispatch_itemsEyyy + 663
32 QuartzCore 0x00000001124084a2 _ZL22display_timer_callbackP12__CFMachPortPvlS1_ + 297
33 CoreFoundation 0x0000000115b46096 __CFMachPortPerform + 150
34 CoreFoundation 0x0000000115b72419 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
35 CoreFoundation 0x0000000115b71a7b __CFRunLoopDoSource1 + 459
36 CoreFoundation 0x0000000115b6c00a __CFRunLoopRun + 2490
37 CoreFoundation 0x0000000115b6b302 CFRunLoopRunSpecific + 626
38 GraphicsServices 0x00000001197dc2fe GSEventRunModal + 65
39 UIKitCore 0x0000000120226ba2 UIApplicationMain + 140
40 TOSCollect Live 0x000000010f16200b main + 75
41 libdyld.dylib 0x0000000117743541 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
当我选择在地图上不可见的注释时,问题出现了。我很乱。
我解决了这个问题,方法是先缩放到该位置,然后将注释 属性 设置为选中状态。
所以我更新了mapViewAnimateTo
方法。
func mapViewAnimateTo(_ index: Int) {
print("MapView scrolling to index \(index)")
let point = presenter.getCollectedPoints(index).coordinates
let coordinate = CLLocationCoordinate2D(latitude: point[0].latitude, longitude: point[0].longitude)
CATransaction.begin()
CATransaction.setCompletionBlock({
// 2. Upon completion of zooming, marks the first annotation found at respective coordinate as selected.
if let annotation = self.mapView.annotations.filter ({ [=10=].coordinate.latitude == coordinate.latitude && [=10=].coordinate.longitude == coordinate.longitude }).first {
self.mapView.selectAnnotation(annotation, animated: true)
}
})
// 1. Zooms to the respective coordinate.
mapView.animateToPoint(coordinate, animated: true)
CATransaction.commit()
}
甚至将区域的距离更新为 10 米。
extension MKMapView {
func animateToPoint(_ coordinate: CLLocationCoordinate2D, animated: Bool) {
let coordinateRegion = MKCoordinateRegion(center: coordinate, latitudinalMeters: 10, longitudinalMeters: 10)
self.setRegion(coordinateRegion, animated: animated)
}
}