为啥不调用 ViewForAnnotation?
Posted
技术标签:
【中文标题】为啥不调用 ViewForAnnotation?【英文标题】:Why is ViewForAnnotation not called?为什么不调用 ViewForAnnotation? 【发布时间】:2016-07-15 00:35:17 【问题描述】:我知道这个问题已被多次询问,但所有答案似乎都与我的应用程序中发生的情况略有不同。
我的理解是,一旦 mapView 将其委托设置为在其中显示它的 ViewController 并且当 mapView 滚动以显示在 mapView 区域内时,将向地图添加注释,就会调用 viewForAnnotation 函数。
目前我有一个包含一个 MKMapView (mapView) 的主 viewController (mainVC) 这个 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()
有几个不同的类可以控制每个不同地图的功能:
-
地图 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 的委托设置为当前类 (mapView.delegate = self)
它会放大正确的位置 (mapView.setRegion(coordinateRegion, animated: true))该类从 plist 中读取并(使用辅助类)构建自定义 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 Annotation(有效),但不会调用 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 从未被触发 - 我认为这应该是有效的,当我“滚动”地图时,它会显示在应该触发该功能的当前视图区域,但它没有(我应该注意到该图钉正在显示并显示在地图上)。
这使得我无法自定义我想做的图钉。
我使用与 Map 1 相同的技术,效果非常好,但出于某种原因,从未在 Map 4 中调用 ViewForAnnotation。
任何建议将不胜感激!
【问题讨论】:
一些代码可能会有所帮助 我添加了代码。现在我注意到,当我从 Map1 更改为 Map4 回到 Map1 时,只有某些时候我的自定义注释会显示我想要的图像。其他时候,它们只用图钉显示。 我玩过很多东西,我认为这一定与委托有关。尽管正在设置委托,但它好像没有正确设置为正在显示的 MKMapView 的实例(尽管在 func loadMap4View(mV: MKMapView) 方法的第一行中进行了设置)。是否与传递给单独类(通过引用或类型传递)的 mV 参数有关?有什么想法吗? 奇怪的功能:在 MainVC 上,不同的地图是通过使用分段控件来选择的。当我快速按下不同的按钮来加载不同的地图时,大约有 10% 的时间程序会中断并到达 ViewForAnnotation 方法内部的断点(这是我想要发生的)。为什么只有 10% 的时间?在某些情况下我无法复制它,它似乎完全是随机的。 如果您在 AsyncQueue 中添加注释,请在 mainQueue 中添加注释。 ***.com/questions/3821515/… 【参考方案1】:我不时遇到这个问题。我发现有时你需要像这样手动调用showAnnotations:animated:
:
mapView.showAnnotations(mapView.annotations, animated: true)
【讨论】:
它工作得稍微好一些,但仍然相当有问题。 ViewForAnnotation 几乎是随机触发的,有时会生成图像而不是 pin 注释,而其他时候则不会。 @M.Black 问题可能位于“mapView = mV”。更合适的方法是:1。删除旧的mapview,2.设置新的mapview的框架与旧的mapview相同,3.添加新的mapview 这是最接近工作的解决方案,尽管它似乎仍然随机调用 ViewForAnnotation 方法并且仅在某些时候加载适当的图像。抱歉 wj2061 没有将赏金授予您(我不确定为什么将其授予其他解决方案???)【参考方案2】:抱歉,我看不到您的视图控制器 mainVC 的声明:您的控制器实现了 MKMapViewDelegate
?
import MapKit
class mainVC: UIViewController, MKMapViewDelegate
...
编辑 1: 还要检查您的故事板上的视图控制器是否像这样与您的控制器链接:
只需右键单击您的 mapView。
【讨论】:
是的。所有其他类也是如此 委托在代码中设置(如上所示)。我很惊讶这个解决方案收到了赞成票,因为它没有解释为什么它在某些时候有效,而在其他时候无效。有四个不同的类负责加载 MainVC 上的 mapView。因此,我不希望委托成为主视图控制器,因为代码包含在每个单独地图的其他视图控制器类中。【参考方案3】:这是一个非常愚蠢的答案,但今天它让我感到两次,所以这里是:检查你的纬度/经度。如果您将它们交换,则您有一个无效点,或者一个位于海洋中间的点,因此永远不会请求视图,因为它可能在您的可见矩形之外。
【讨论】:
以上是关于为啥不调用 ViewForAnnotation?的主要内容,如果未能解决你的问题,请参考以下文章
强制 MKMapView viewForAnnotation 更新
iPhone MapKit 问题:viewForAnnotation 设置 pinColor 不一致?