SwiftUI 中的自定义注解 (MKMapView)
Custom Annotations in SwiftUI (MKMapView)
我在 SwiftUI 中实现了一个 MKMapView,我正在显示注释(停靠点)列表以及用户的位置。
我想将水龙头功能添加到“停止引脚”,但我找不到任何有助于实现此目的的东西。
此代码的问题在于它更改了用户定位图钉的视图并最终因以下错误而崩溃。
2021-07-10 18:31:21.434538+0900 Bus Finder[5232:2086940] *** Terminating app due to uncaught exception 'NSGenericException', reason: '<Bus_Finder.Stops: 0x2816c4cc0> must implement title, or view (null) must have a non-nil detailCalloutAccessoryView when canShowCallout is YES on corresponding view <MKAnnotationView: 0x13137cd60; frame = (-20 -20; 40 40); opaque = NO; layer = <CALayer: 0x2832e9e20>>'
*** First throw call stack:
(0x196f2a754 0x1ab9f17a8 0x1a6566410 0x1a65655bc 0x1a656464c 0x1a65641d0 0x1982fd458 0x196ea522c 0x196ea4e28 0x196ea4278 0x196e9e02c 0x196e9d360 0x1ae4db734 0x199918584 0x19991ddf4 0x19ddf3370 0x19ddf32fc 0x19d8ebb6c 0x100eacf54 0x100eacff4 0x196b59cf8)
libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSGenericException', reason: '<Bus_Finder.Stops: 0x2816c4cc0> must implement title, or view (null) must have a non-nil detailCalloutAccessoryView when canShowCallout is YES on corresponding view <MKAnnotationView: 0x13137cd60; frame = (-20 -20; 40 40); opaque = NO; layer = <CALayer: 0x2832e9e20>>'
terminating with uncaught exception of type NSException
我只想更改“stops pin”的视图并添加点击功能。
我在出现时将停止列表传递给 MapView
。 Stops
结构在最后。
我的问题的视觉概念:
(注释viewFor注解函数时)
我想更改停止图钉的样式并向其添加点击功能,而不是用户的位置图钉。
当我使用 viewFor 注释功能(与本问题中的代码相同)时,用户位置视图发生变化,然后应用程序崩溃。
MapView
文件:
// MARK: MapView
struct MapView: UIViewRepresentable {
// MARK: Variables
@Binding var stops: [Stops]
@Binding var centerCoordinate: MKCoordinateRegion
@Binding var action: Action
// MARK: Action Lists
enum Action {
case idle
case reset(coordinate: MKCoordinateRegion)
case changeType(mapType: MKMapType)
}
// MARK: First Time Only
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView()
mapView.delegate = context.coordinator
mapView.showsUserLocation = true
mapView.userTrackingMode = .follow
mapView.isUserInteractionEnabled = true
mapView.centerCoordinate = self.centerCoordinate.center
mapView.setRegion(self.centerCoordinate, animated: true)
return mapView
}
// MARK: Updating UI
func updateUIView(_ view: MKMapView, context: Context) {
switch action {
case .idle:
break
case .reset(let newCoordinate):
view.delegate = nil
DispatchQueue.main.async {
self.centerCoordinate.center = newCoordinate.center
self.action = .idle
view.setRegion(self.centerCoordinate, animated: true)
view.delegate = context.coordinator
}
case .changeType(let mapType):
view.mapType = mapType
}
view.addAnnotations(stops)
}
// MARK: Setting Coordinator
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, MKMapViewDelegate {
var parent: MapView
init(_ parent: MapView) {
self.parent = parent
}
func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
parent.centerCoordinate.center = mapView.centerCoordinate
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "TESTING NOTE")
annotationView.canShowCallout = true
annotationView.image = UIImage(systemName: "location.circle")?.withTintColor(.systemGreen, renderingMode: .alwaysOriginal)
let size = CGSize(width: 40, height: 40)
annotationView.image = UIGraphicsImageRenderer(size:size).image {
_ in annotationView.image!.draw(in:CGRect(origin:.zero, size:size))
}
return annotationView
}
}
}
Stops
结构文件:
// MARK: StopPinPoint
final class Stops: NSObject, Codable, Identifiable, MKAnnotation {
var id: String?
var name: BusStopName
var images: [String]?
var landMarks: [String]?
var coordinate: CLLocationCoordinate2D
var prevNexStop: [String]?
init(id: String?, name: BusStopName, images: [String]?, landMarks: [String]?, coordinates: CLLocationCoordinate2D, prevNextStop: [String]?) {
self.id = id
self.name = name
self.coordinate = coordinates
self.images = images
self.landMarks = landMarks
self.prevNexStop = prevNextStop
}
var location: CLLocation {
return CLLocation(latitude: self.coordinate.latitude, longitude: self.coordinate.longitude)
}
func distance(to location: CLLocation) -> CLLocationDistance {
return location.distance(from: self.location)
}
}
如果有人能帮助我,我将不胜感激!几个星期以来我一直在研究这个问题!
所以基本上在多搜索之后,我找到了答案。
为了不改变用户的位置 pin,我必须检查注释的类型,如果类型是 MKUserLocation
我应该 return nil。
接下来崩溃的原因是我必须让 Stops
结构确认 MKPointAnnotation
并删除或覆盖坐标变量然后当我制作 [=11 的列表时=] 我可以简单地定义标题、副标题和坐标。
我在 SwiftUI 中实现了一个 MKMapView,我正在显示注释(停靠点)列表以及用户的位置。 我想将水龙头功能添加到“停止引脚”,但我找不到任何有助于实现此目的的东西。
此代码的问题在于它更改了用户定位图钉的视图并最终因以下错误而崩溃。
2021-07-10 18:31:21.434538+0900 Bus Finder[5232:2086940] *** Terminating app due to uncaught exception 'NSGenericException', reason: '<Bus_Finder.Stops: 0x2816c4cc0> must implement title, or view (null) must have a non-nil detailCalloutAccessoryView when canShowCallout is YES on corresponding view <MKAnnotationView: 0x13137cd60; frame = (-20 -20; 40 40); opaque = NO; layer = <CALayer: 0x2832e9e20>>'
*** First throw call stack:
(0x196f2a754 0x1ab9f17a8 0x1a6566410 0x1a65655bc 0x1a656464c 0x1a65641d0 0x1982fd458 0x196ea522c 0x196ea4e28 0x196ea4278 0x196e9e02c 0x196e9d360 0x1ae4db734 0x199918584 0x19991ddf4 0x19ddf3370 0x19ddf32fc 0x19d8ebb6c 0x100eacf54 0x100eacff4 0x196b59cf8)
libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSGenericException', reason: '<Bus_Finder.Stops: 0x2816c4cc0> must implement title, or view (null) must have a non-nil detailCalloutAccessoryView when canShowCallout is YES on corresponding view <MKAnnotationView: 0x13137cd60; frame = (-20 -20; 40 40); opaque = NO; layer = <CALayer: 0x2832e9e20>>'
terminating with uncaught exception of type NSException
我只想更改“stops pin”的视图并添加点击功能。
我在出现时将停止列表传递给 MapView
。 Stops
结构在最后。
我的问题的视觉概念:
(注释viewFor注解函数时) 我想更改停止图钉的样式并向其添加点击功能,而不是用户的位置图钉。
当我使用 viewFor 注释功能(与本问题中的代码相同)时,用户位置视图发生变化,然后应用程序崩溃。
MapView
文件:
// MARK: MapView
struct MapView: UIViewRepresentable {
// MARK: Variables
@Binding var stops: [Stops]
@Binding var centerCoordinate: MKCoordinateRegion
@Binding var action: Action
// MARK: Action Lists
enum Action {
case idle
case reset(coordinate: MKCoordinateRegion)
case changeType(mapType: MKMapType)
}
// MARK: First Time Only
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView()
mapView.delegate = context.coordinator
mapView.showsUserLocation = true
mapView.userTrackingMode = .follow
mapView.isUserInteractionEnabled = true
mapView.centerCoordinate = self.centerCoordinate.center
mapView.setRegion(self.centerCoordinate, animated: true)
return mapView
}
// MARK: Updating UI
func updateUIView(_ view: MKMapView, context: Context) {
switch action {
case .idle:
break
case .reset(let newCoordinate):
view.delegate = nil
DispatchQueue.main.async {
self.centerCoordinate.center = newCoordinate.center
self.action = .idle
view.setRegion(self.centerCoordinate, animated: true)
view.delegate = context.coordinator
}
case .changeType(let mapType):
view.mapType = mapType
}
view.addAnnotations(stops)
}
// MARK: Setting Coordinator
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, MKMapViewDelegate {
var parent: MapView
init(_ parent: MapView) {
self.parent = parent
}
func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
parent.centerCoordinate.center = mapView.centerCoordinate
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "TESTING NOTE")
annotationView.canShowCallout = true
annotationView.image = UIImage(systemName: "location.circle")?.withTintColor(.systemGreen, renderingMode: .alwaysOriginal)
let size = CGSize(width: 40, height: 40)
annotationView.image = UIGraphicsImageRenderer(size:size).image {
_ in annotationView.image!.draw(in:CGRect(origin:.zero, size:size))
}
return annotationView
}
}
}
Stops
结构文件:
// MARK: StopPinPoint
final class Stops: NSObject, Codable, Identifiable, MKAnnotation {
var id: String?
var name: BusStopName
var images: [String]?
var landMarks: [String]?
var coordinate: CLLocationCoordinate2D
var prevNexStop: [String]?
init(id: String?, name: BusStopName, images: [String]?, landMarks: [String]?, coordinates: CLLocationCoordinate2D, prevNextStop: [String]?) {
self.id = id
self.name = name
self.coordinate = coordinates
self.images = images
self.landMarks = landMarks
self.prevNexStop = prevNextStop
}
var location: CLLocation {
return CLLocation(latitude: self.coordinate.latitude, longitude: self.coordinate.longitude)
}
func distance(to location: CLLocation) -> CLLocationDistance {
return location.distance(from: self.location)
}
}
如果有人能帮助我,我将不胜感激!几个星期以来我一直在研究这个问题!
所以基本上在多搜索之后,我找到了答案。
为了不改变用户的位置 pin,我必须检查注释的类型,如果类型是 MKUserLocation
我应该 return nil。
接下来崩溃的原因是我必须让 Stops
结构确认 MKPointAnnotation
并删除或覆盖坐标变量然后当我制作 [=11 的列表时=] 我可以简单地定义标题、副标题和坐标。