为什么不调用 ViewForAnnotation?
Why is ViewForAnnotation not called?
我知道这个问题已被问过多次,但所有答案似乎都与我的应用程序中发生的情况略有不同。
我的理解是,一旦 mapView 将其委托设置为显示它的 ViewController 并且在 mapView 滚动时将注释添加到地图,就会调用 viewForAnnotation 函数,以便它显示在 mapView 区域内。
目前我有一个主 viewController (mainVC) 包含一个 MKMapView (mapView)
这个viewController控制了四个不同的地图在mapView中显示。
func moveViews(sender:Int) {
// This function handles which button on the Segmented Control was clicked and the loads the appropriate map into the mapView (passed as a para
removeAnnotationsAndOverlays() // ~~~
if sender == 0 {
// First Map was selected
let map1VC = map1VC()
map1VC.loadMap1View(mapView)
map1VC.centerMapOnLocation()
}
else if sender == 1 {
// Second Map was selected
let map2VC = map2VC()
map2VC.loadMap2View(mapView)
}
else if sender == 2 {
// Third Map was selected
let map3VC = map3VC()
map3VC.loadMap3View(mapView)
}
else if sender == 3 {
// Fourth Map was selected
let map4VC = map4VC()
map4VC.loadMap4View(mapView)
}
else {
// Load First Map as default
let map1VC = map1VC()
map1VC.loadMap1View(mapView)
map1VC.centerMapOnLocation()
}
}
有几个不同的 classes 控制每个不同地图的功能:
- 地图 1 - 显示从 plist 读取的 MKPolylines 和自定义注释(继承自 MKAnnotation)的组合 - 这很好用!
- 地图 2 - 显示从 plist 读取的多个 MKPolylines - 这很好用!
- 地图 3 - 显示从 plist 读取的多个 MKPolylines - 这很好用!
- 地图 4 - 应该显示几个自定义注释 - 这不起作用!
地图 4 的情况如下:
正在正确加载 MKMapView
var mapView: MKMapView = MKMapView() // declared as a global variable/object inside the map4VC()
// Initial function to set up Map
// Think of this function as the "override func viewDidLoad() {}"
func loadMap4View(mV: MKMapView) {
// This connects the parameter passed (mV) and sets it as the delegate for the mapView used throughout this file
// In other words, it allows the mapView on the MainVC to use all of the code in this file to handle different actions
mapView = mV
mapView.delegate = self
let initialLocation = CLLocation(latitude: 50.3603125, longitude: 2.794017)
// calculates the region you'll look at on the screen
let coordinateRegion = MKCoordinateRegionMakeWithDistance(initialLocation.coordinate, regionRadius, regionRadius)
// sets the region of the map
mapView.setRegion(coordinateRegion, animated: true)
//addPins() // This can use a custom function to load all of the Pins
//mapView.addAnnotations(coords.allLocations!) // This line also works to add all of the individual pins
mapView.addAnnotation(coords.allLocations![2]) // This adds one single Pin
}
将 mapView 的委托设置为当前 class (mapView.delegate = self)
- 它在适当的位置放大 (mapView.setRegion(coordinateRegion, animated: true))
class 从 plist 读取并(使用助手 class)构建自定义 MKAnnotations (CemAnno) 数组
位置存储在名为 allLocations 的 CemAnno 数组中:
var allLocations: [CemAnno]? = [] // This is declared in the helper class along with a bunch of other stuff that grabs all of the information from a plist
class CemAnno: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
var casualties: String?
var visitInfo: String?
var histInfo: String?
var region: String?
init(title: String, coordinate: CLLocationCoordinate2D, region: String, casualties: String, visitInfo: String, histInfo: String) {
self.coordinate = coordinate
self.title = title
self.region = region
self.casualties = casualties
self.visitInfo = visitInfo
self.histInfo = histInfo
}
}
// This builds an object inside the the map4VC() class called coords that holds all of the information collected from the plist
var coords = BuildCoordinates(filename: "Coordinate")
将其中的每一个添加到地图 (mapView.addAnnotations) 并将它们显示为图钉(它们正在显示)
mapView.addAnnotation(coords.allLocations![2]) // 这添加了一个 Pin 注释(有效)但从不调用 viewForAnnotation 函数
这行得通,但是,我正在尝试自定义正在显示的注释,但从未调用 ViewForAnnotation 函数????
// This function is NEVER called
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?
{
// Define a reuse identifier. This is a string that will be used to ensure we reuse annotation views as much as possible.
let identifier = "CemAnno"
// Check whether the annotation we're creating a view for is one of our CemAnno objects.
if annotation.isKindOfClass(CemAnno.self) {
print("correct class")
//let anno = annotation as! CustomAnnotation
// Try to dequeue an annotation view from the map view's pool of unused views.
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if annotationView == nil {
print("no reusable view")
// If it isn't able to find a reusable view, create a new one using MKPinAnnotationView and sets its canShowCallout property to be true. This triggers the popup with the name.
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView!.canShowCallout = true
// Create a new UIButton using the built-in .Custom type. This is so we can add an image to the button.
let btn = UIButton(type: .DetailDisclosure)
//btn.setImage(anno.image, forState: .Normal)
annotationView!.rightCalloutAccessoryView = btn
} else {
print("reusing a view")
// If it can reuse a view, update that view to use a different annotation.
annotationView!.annotation = annotation
}
return annotationView
}
// If the annotation isn't from a CustomClass, it must return nil so iOS uses a default view.
return MKPinAnnotationView()
}
我已经尝试在地图的当前视图区域内添加图钉的位置,但从未触发 ViewForAnnotation。
我已经尝试在地图的当前视图区域之外添加图钉的位置,但是 ViewForAnnotation 从未被触发 - 我认为这应该是有效的,并且当我 'scroll' 地图并且它出现时在应该触发该功能的当前视图区域内,但它没有(我应该注意到图钉正在显示并显示在地图上)。
这使得我无法自定义我想做的引脚。
我使用与 Map 1 相同的技术,它工作得很好,但出于某种原因,从未在 Map 4 中调用 ViewForAnnotation。
如有任何建议,我们将不胜感激!!
抱歉,我看不到您的视图控制器的声明 mainVC:您的控制器实现了 MKMapViewDelegate
?
import MapKit
class mainVC: UIViewController, MKMapViewDelegate
{
...
}
编辑 1: 还要检查是否在你的故事板上的视图控制器中,如果委托与你的控制器链接如下:
只需右键单击您的 mapView。
我不时遇到这个问题 time.And 我发现有时你需要像这样手动调用 showAnnotations:animated:
:
mapView.showAnnotations(mapView.annotations, animated: true)
这是一个非常愚蠢的答案,但今天它咬了我两次所以在这里:检查你的 latitude/longitude。如果你交换了它们,你有一个无效的点,或者一个在海洋中间,所以视图将永远不会被请求,因为它很可能在你的可见矩形之外。
我知道这个问题已被问过多次,但所有答案似乎都与我的应用程序中发生的情况略有不同。
我的理解是,一旦 mapView 将其委托设置为显示它的 ViewController 并且在 mapView 滚动时将注释添加到地图,就会调用 viewForAnnotation 函数,以便它显示在 mapView 区域内。
目前我有一个主 viewController (mainVC) 包含一个 MKMapView (mapView) 这个viewController控制了四个不同的地图在mapView中显示。
func moveViews(sender:Int) {
// This function handles which button on the Segmented Control was clicked and the loads the appropriate map into the mapView (passed as a para
removeAnnotationsAndOverlays() // ~~~
if sender == 0 {
// First Map was selected
let map1VC = map1VC()
map1VC.loadMap1View(mapView)
map1VC.centerMapOnLocation()
}
else if sender == 1 {
// Second Map was selected
let map2VC = map2VC()
map2VC.loadMap2View(mapView)
}
else if sender == 2 {
// Third Map was selected
let map3VC = map3VC()
map3VC.loadMap3View(mapView)
}
else if sender == 3 {
// Fourth Map was selected
let map4VC = map4VC()
map4VC.loadMap4View(mapView)
}
else {
// Load First Map as default
let map1VC = map1VC()
map1VC.loadMap1View(mapView)
map1VC.centerMapOnLocation()
}
}
有几个不同的 classes 控制每个不同地图的功能:
- 地图 1 - 显示从 plist 读取的 MKPolylines 和自定义注释(继承自 MKAnnotation)的组合 - 这很好用!
- 地图 2 - 显示从 plist 读取的多个 MKPolylines - 这很好用!
- 地图 3 - 显示从 plist 读取的多个 MKPolylines - 这很好用!
- 地图 4 - 应该显示几个自定义注释 - 这不起作用!
地图 4 的情况如下:
正在正确加载 MKMapView
var mapView: MKMapView = MKMapView() // declared as a global variable/object inside the map4VC() // Initial function to set up Map // Think of this function as the "override func viewDidLoad() {}" func loadMap4View(mV: MKMapView) { // This connects the parameter passed (mV) and sets it as the delegate for the mapView used throughout this file // In other words, it allows the mapView on the MainVC to use all of the code in this file to handle different actions mapView = mV mapView.delegate = self let initialLocation = CLLocation(latitude: 50.3603125, longitude: 2.794017) // calculates the region you'll look at on the screen let coordinateRegion = MKCoordinateRegionMakeWithDistance(initialLocation.coordinate, regionRadius, regionRadius) // sets the region of the map mapView.setRegion(coordinateRegion, animated: true) //addPins() // This can use a custom function to load all of the Pins //mapView.addAnnotations(coords.allLocations!) // This line also works to add all of the individual pins mapView.addAnnotation(coords.allLocations![2]) // This adds one single Pin
}
将 mapView 的委托设置为当前 class (mapView.delegate = self)
- 它在适当的位置放大 (mapView.setRegion(coordinateRegion, animated: true))
class 从 plist 读取并(使用助手 class)构建自定义 MKAnnotations (CemAnno) 数组
位置存储在名为 allLocations 的 CemAnno 数组中:
var allLocations: [CemAnno]? = [] // This is declared in the helper class along with a bunch of other stuff that grabs all of the information from a plist class CemAnno: NSObject, MKAnnotation { var coordinate: CLLocationCoordinate2D var title: String? var casualties: String? var visitInfo: String? var histInfo: String? var region: String? init(title: String, coordinate: CLLocationCoordinate2D, region: String, casualties: String, visitInfo: String, histInfo: String) { self.coordinate = coordinate self.title = title self.region = region self.casualties = casualties self.visitInfo = visitInfo self.histInfo = histInfo }
}
// This builds an object inside the the map4VC() class called coords that holds all of the information collected from the plist var coords = BuildCoordinates(filename: "Coordinate")
将其中的每一个添加到地图 (mapView.addAnnotations) 并将它们显示为图钉(它们正在显示) mapView.addAnnotation(coords.allLocations![2]) // 这添加了一个 Pin 注释(有效)但从不调用 viewForAnnotation 函数
这行得通,但是,我正在尝试自定义正在显示的注释,但从未调用 ViewForAnnotation 函数????
// This function is NEVER called
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?
{
// Define a reuse identifier. This is a string that will be used to ensure we reuse annotation views as much as possible.
let identifier = "CemAnno"
// Check whether the annotation we're creating a view for is one of our CemAnno objects.
if annotation.isKindOfClass(CemAnno.self) {
print("correct class")
//let anno = annotation as! CustomAnnotation
// Try to dequeue an annotation view from the map view's pool of unused views.
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if annotationView == nil {
print("no reusable view")
// If it isn't able to find a reusable view, create a new one using MKPinAnnotationView and sets its canShowCallout property to be true. This triggers the popup with the name.
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView!.canShowCallout = true
// Create a new UIButton using the built-in .Custom type. This is so we can add an image to the button.
let btn = UIButton(type: .DetailDisclosure)
//btn.setImage(anno.image, forState: .Normal)
annotationView!.rightCalloutAccessoryView = btn
} else {
print("reusing a view")
// If it can reuse a view, update that view to use a different annotation.
annotationView!.annotation = annotation
}
return annotationView
}
// If the annotation isn't from a CustomClass, it must return nil so iOS uses a default view.
return MKPinAnnotationView()
}
我已经尝试在地图的当前视图区域内添加图钉的位置,但从未触发 ViewForAnnotation。 我已经尝试在地图的当前视图区域之外添加图钉的位置,但是 ViewForAnnotation 从未被触发 - 我认为这应该是有效的,并且当我 'scroll' 地图并且它出现时在应该触发该功能的当前视图区域内,但它没有(我应该注意到图钉正在显示并显示在地图上)。
这使得我无法自定义我想做的引脚。
我使用与 Map 1 相同的技术,它工作得很好,但出于某种原因,从未在 Map 4 中调用 ViewForAnnotation。
如有任何建议,我们将不胜感激!!
抱歉,我看不到您的视图控制器的声明 mainVC:您的控制器实现了 MKMapViewDelegate
?
import MapKit
class mainVC: UIViewController, MKMapViewDelegate
{
...
}
编辑 1: 还要检查是否在你的故事板上的视图控制器中,如果委托与你的控制器链接如下:
只需右键单击您的 mapView。
我不时遇到这个问题 time.And 我发现有时你需要像这样手动调用 showAnnotations:animated:
:
mapView.showAnnotations(mapView.annotations, animated: true)
这是一个非常愚蠢的答案,但今天它咬了我两次所以在这里:检查你的 latitude/longitude。如果你交换了它们,你有一个无效的点,或者一个在海洋中间,所以视图将永远不会被请求,因为它很可能在你的可见矩形之外。