mapView:viewForAnnotation 什么时候在 Swift 中被调用?
When is mapView:viewForAnnotation called in Swift?
根据 this post 每当您调用 addAnnotation
方法时,都会调用 mapView:viewForAnnotation
但是下面的代码只调用了一次mapView:viewForAnnotation
。我有几个注释,但 "view called" 只打印了一次。我猜这与线程有关?
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, UITextFieldDelegate, MKMapViewDelegate, CLLocationManagerDelegate {
@IBOutlet var searchtext: UITextField!
@IBOutlet var map: MKMapView!
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
self.searchtext.delegate = self
locationManager.delegate = self
self.map.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
func textFieldDidBeginEditing(textField: UITextField!) { //delegate method
var allAnnotations = self.map.annotations
self.map.removeAnnotations(allAnnotations)
}
func textFieldShouldReturn(textField: UITextField!) ->Bool {
textField.resignFirstResponder()
//...
let session = NSURLSession.sharedSession()
var task = session.dataTaskWithURL(url!, completionHandler: { (date, response, error) -> Void in
if (error != nil) {
println(error)
}else {
var placenum = 0
//placenum is to see if all the places are in the visible rect. If so I will use showAnnotations to zoom (in) to the best-fitted view show them. If not, I will only show these in the visible rect
for place in places {
//...
if (regionContains(self.map.region, coordinate)) {
placenum = placenum+1
}
self.map.addAnnotation(annotation)
}
if (placenum==places.count) {
self.map.showAnnotations(self.map.annotations, animated: true)
}
}
})
task.resume()
return true
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
//...
self.map.setRegion(region, animated: false)
locationManager.stopUpdatingLocation()
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
println("view called")
return nil
}
简而言之,当注释位于地图视图的可见部分时,将调用 mapView(_:viewFor:)
。即,(a) 注释已添加到地图视图并且它与 region
一起落下,或者 (b) region
更改使得以前不可见的注释现在可见。不用说,如果您设置地图视图的委托(以编程方式或在 Interface Builder 中),此方法也只会被调用。
顺便说一下,dataTask(with:completionHandler:)
的完成处理程序不会在主线程上调用。因此,任何 UI 更新都必须显式分派回主线程,例如
DispatchQueue.main.async {
for place in places {
//...
placenum = placenum + 1
self.map.addAnnotation(annotation)
}
self.map.showAnnotations(self.map.annotations, animated: true)
}
我建议确保与地图视图的交互发生在主线程上,如上所示。
顺便说一句,请记住,如果您在地图上显示用户位置,这本身会导致 mapView(_:viewFor:)
被调用。因此,如果您看到它只被调用一次,您可能需要确认 annotation
是 MKUserLocation
还是您添加的注释之一。
另外请确保将 mapview 的委托 属性 设置为自己。
mapview.delegate = self
您也可以使用连接检查器(界面生成器)
将 mapview 的委托出口连接到 ViewController
根据 this post 每当您调用 addAnnotation
方法时,都会调用 mapView:viewForAnnotation
但是下面的代码只调用了一次mapView:viewForAnnotation
。我有几个注释,但 "view called" 只打印了一次。我猜这与线程有关?
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, UITextFieldDelegate, MKMapViewDelegate, CLLocationManagerDelegate {
@IBOutlet var searchtext: UITextField!
@IBOutlet var map: MKMapView!
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
self.searchtext.delegate = self
locationManager.delegate = self
self.map.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
func textFieldDidBeginEditing(textField: UITextField!) { //delegate method
var allAnnotations = self.map.annotations
self.map.removeAnnotations(allAnnotations)
}
func textFieldShouldReturn(textField: UITextField!) ->Bool {
textField.resignFirstResponder()
//...
let session = NSURLSession.sharedSession()
var task = session.dataTaskWithURL(url!, completionHandler: { (date, response, error) -> Void in
if (error != nil) {
println(error)
}else {
var placenum = 0
//placenum is to see if all the places are in the visible rect. If so I will use showAnnotations to zoom (in) to the best-fitted view show them. If not, I will only show these in the visible rect
for place in places {
//...
if (regionContains(self.map.region, coordinate)) {
placenum = placenum+1
}
self.map.addAnnotation(annotation)
}
if (placenum==places.count) {
self.map.showAnnotations(self.map.annotations, animated: true)
}
}
})
task.resume()
return true
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
//...
self.map.setRegion(region, animated: false)
locationManager.stopUpdatingLocation()
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
println("view called")
return nil
}
简而言之,当注释位于地图视图的可见部分时,将调用 mapView(_:viewFor:)
。即,(a) 注释已添加到地图视图并且它与 region
一起落下,或者 (b) region
更改使得以前不可见的注释现在可见。不用说,如果您设置地图视图的委托(以编程方式或在 Interface Builder 中),此方法也只会被调用。
顺便说一下,dataTask(with:completionHandler:)
的完成处理程序不会在主线程上调用。因此,任何 UI 更新都必须显式分派回主线程,例如
DispatchQueue.main.async {
for place in places {
//...
placenum = placenum + 1
self.map.addAnnotation(annotation)
}
self.map.showAnnotations(self.map.annotations, animated: true)
}
我建议确保与地图视图的交互发生在主线程上,如上所示。
顺便说一句,请记住,如果您在地图上显示用户位置,这本身会导致 mapView(_:viewFor:)
被调用。因此,如果您看到它只被调用一次,您可能需要确认 annotation
是 MKUserLocation
还是您添加的注释之一。
另外请确保将 mapview 的委托 属性 设置为自己。
mapview.delegate = self
您也可以使用连接检查器(界面生成器)
将 mapview 的委托出口连接到 ViewController