Swift 3 中未调用 ViewForAnnotation

Posted

技术标签:

【中文标题】Swift 3 中未调用 ViewForAnnotation【英文标题】:ViewForAnnotation not Called in Swift 3 【发布时间】:2016-11-25 04:57:30 【问题描述】:

我想在单击 PinAnnotation 时打开一个新的视图控制器。但是当我单击时 ViewForannotation 没有调用,但是当我单击 Pin 时它显示一条弹出消息。不知道发生了什么。这是我的代码:

import UIKit
import MapKit

class Pin: NSObject, MKAnnotation 

    var coordinate: CLLocationCoordinate2D
    var key: String
    var title: String?
    var age: String?
    var category: String?
    var color: MKPinAnnotationColor = MKPinAnnotationColor.purple
    var subtitle: String?

    init(key: String, name: String , age: String , category: String , color: MKPinAnnotationColor) 
        self.coordinate = CLLocationCoordinate2D(latitude: 0, longitude: 0)
        self.key = key
        self.title = name
        self.color = color
        self.subtitle = age
        self.category = category


        //print("keyy: ", key)
        //print("title: ", name)
    


这是我的 MapViewControllerClass:

import UIKit
import GeoFire
import MapKit
import Firebase
import CoreLocation


class MapViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate, UIAlertViewDelegate 

    //@IBOutlet weak var sidebarButton: UIBarButtonItem!
    @IBOutlet weak var mapView: MKMapView!
    //@IBOutlet weak var chatbarButton: UIBarButtonItem!

    /* ---> NEW MAP-IT <--- */

    let locationManager = CLLocationManager()

    let imagePicker = UIImagePickerController()
    var regionQuery: GFRegionQuery?
    var foundQuery: GFCircleQuery?
    var annotations: Dictionary<String, Pin> = Dictionary(minimumCapacity: 8)

    var lastExchangeKeyFound: String?
    var lastExchangeLocationFound: CLLocation?

    var location: CLLocation!
   // var location = CLLocation(latitude: 37.33233141, longitude: -122.0312186)
    //let location = CLLocation(latitude: 37.33209999, longitude: -122.0326666)

    var circle: MKCircle!

    var index = 0
    var val1Lat: Double!
    var val2Lat: Double!
    var val1Long: Double!
    var val2Long: Double!

    var flag = false
    var userName = ""
    var age = ""
    var category = ""
    var uid = ""

    override func viewDidLoad() 
        super.viewDidLoad()

        uid = DataService.ds.currentUserID
        self.mapView.delegate = self
        // locationManager.requestAlwaysAuthorization()

        if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways) || (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse) 
            print("Authorized")
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.startUpdatingLocation()
         else 
            print("Application is not authorized to use location services")
            //- TODO: Unauthorized, requests permissions again and makes recursive call
        
    

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 
        if manager.location?.coordinate != nil 
            if flag == true 
                if (location.coordinate.latitude != manager.location?.coordinate.latitude) || (location.coordinate.longitude != manager.location?.coordinate.longitude) 

                    location = manager.location!//.coordinate
                    print("lat: \(location.coordinate.latitude)")
                    print("long: \(location.coordinate.longitude)")
                    animateMap(location: location)

                    let key = DataService.ds.currentUserID
                    geofire!.setLocation(location, forKey: key)
                
             else 
                print("Else:LocationManag")
                location = manager.location!
                print("lat: \(location.coordinate.latitude)")
                print("long: \(location.coordinate.longitude)")

                animateMap(location: location)
                flag = true

                let key = DataService.ds.currentUserID
                geofire!.setLocation(location, forKey: key)
            
        
    

    override func viewDidAppear(_ animated: Bool) 
        print("DidAppear")
        self.mapView.userLocation.addObserver(self, forKeyPath: "location", options: NSKeyValueObservingOptions(), context: nil)
    
    override func viewDidDisappear(_ animated: Bool) 
        print("DidDisAppear")
        locationManager.stopUpdatingLocation()
        self.mapView.userLocation.removeObserver(self, forKeyPath: "location", context: nil)
    

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) 
        print("In observer")
        if (self.mapView.showsUserLocation) && (self.mapView.userLocation.location) != nil
        
            let span = MKCoordinateSpanMake(0.0125, 0.0125)
            let region = MKCoordinateRegion(center: self.mapView.userLocation.location!.coordinate /*location.coordinate*/, span: span)

            self.mapView.setRegion(region, animated: true)




            if foundQuery == nil 
                 print("FoundQuery nill")
                foundQuery = geofire?.query(at: /*location*/self.mapView.userLocation.location, withRadius: 0.2)

                foundQuery!.observe(GFEventType.keyEntered, with:  (key: String?, location:CLLocation?)  -> Void in

                    //print("here")
                    DataService.ds.userRef.child(key!).observeSingleEvent(of: .value, with:  (snapshot) in

                        if let userDictionary = snapshot.value as? Dictionary<String , AnyObject>
                        
                            self.userName = userDictionary["firstName"] as! String
                            self.age = userDictionary["age"] as! String
                            self.category = userDictionary["category"] as! String
                        


                        self.lastExchangeKeyFound = key
                        self.lastExchangeLocationFound = location

                        if key != DataService.ds.currentUserID 
                            let annotation = Pin(key: key!, name: self.userName , age: self.age , category: self.category , color: MKPinAnnotationColor.green)

                            annotation.coordinate = (location?.coordinate)!
                            annotation.title = self.userName + " - " + self.age
                            annotation.subtitle = self.category
//                            if self.category == "Trainer"
//                                annotation.color = MKPinAnnotationColor.green
//                            else
//                                annotation.color = MKPinAnnotationColor.purple
//                            
                            self.mapView.addAnnotation(annotation)
                            self.annotations[key!] = annotation
                        
                    )

                    self.foundQuery?.observe(.keyExited, with:  (key, location) in
                        if key != DataService.ds.currentUserID 
                            if self.annotations[key!] != nil 
                                self.mapView.removeAnnotation(self.annotations[key!]!)
                                self.annotations[key!] = nil
                            
                        
                    )
                )
            
            else
            
                foundQuery?.center = self.mapView.userLocation.location
            
        
    

    //Click Event For Annotation:

//    func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!,
//                 calloutAccessoryControlTapped control: UIControl!) 
//        
//        if control == view.rightCalloutAccessoryView 
//            print("Disclosure Pressed! \(view.annotation?.subtitle)")
//        
//        
//    

    func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! 

        print("inPin1")
        if annotation is Pin 
            print("inPin2")
            let pinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myPin")

            pinAnnotationView.pinColor = .purple
            pinAnnotationView.isDraggable = true
            pinAnnotationView.canShowCallout = true
            pinAnnotationView.animatesDrop = true

            let deleteButton = UIButton.init(type: UIButtonType.custom) as UIButton
            // let deleteButton = UIButton.withType(UIButtonType.custom) as UIButton
            deleteButton.frame.size.width = 44
            deleteButton.frame.size.height = 44
            deleteButton.backgroundColor = UIColor.red
            deleteButton.setImage(UIImage(named: "xbutton"), for: .normal)

            pinAnnotationView.leftCalloutAccessoryView = deleteButton

            return pinAnnotationView
        

        return nil
    

    func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) 
        if let annotation = view.annotation as? Pin 
            mapView.removeAnnotation(annotation)
        

    



//    func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView 
//        var annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "loc")
//        annotationView.canShowCallout = true
//        annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
//        return annotationView
//    
//    
//    func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) 
//        mapView.deselectAnnotation(view.annotation, animated: true)
//        var controller = self.storyboard!.instantiateViewController(withIdentifier: "DetailsPopover")
//        controller.annotation! = view.annotation
//        self.popover = UIPopoverController(contentViewController: controller)
//        self.popover.delegate = self
//        self.popover.presentPopoverFromRect(view.frame, inView: view.superview!, permittedArrowDirections: .Any, animated: true)
//    


//    func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) 
//        print("helloooo")
//        self.performSegue(withIdentifier: "detailView", sender: view)
//    

//    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? 
//        // simple and inefficient example
//        let annotationView = MKPinAnnotationView()
//        if category == "Trainer"
//            annotationView.pinTintColor = .purple
//        else
//            annotationView.pinTintColor = .green
//        
//        
//        
//        
//        return annotationView
//    

    func animateMap(location: CLLocation)
    
       // print("animate Map")
        let region = MKCoordinateRegionMakeWithDistance(location.coordinate, 1000, 1000)
        mapView.setRegion(region, animated: true)
        addRadiusCircle(location: location)
    

    func addRadiusCircle(location: CLLocation)
    
        //print("Add Radius")
        //self.mapView.delegate = self

        if circle != nil
        
            self.mapView.remove(circle)
        

        circle = MKCircle(center: location.coordinate, radius: 200 as CLLocationDistance)
        self.mapView.add(circle)
    

    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer
    
        if overlay is MKCircle
        
            let circle = MKCircleRenderer(overlay: overlay)
            circle.strokeColor = UIColor.red
            circle.fillColor = UIColor(red: 255, green: 0, blue: 0, alpha: 0.1)
            circle.lineWidth = 1
            return circle
        
        else 
            let temp = MKOverlayRenderer()
            return temp
        
    

我正在使用 Geofire 获取特定半径内的附近用户,然后锁定该用户。请帮忙。

【问题讨论】:

【参考方案1】:

你是说:

func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView!

那肯定不会被调用。在 Swift 3 中,正确的签名是:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?

您所要做的就是查阅文档:

https://developer.apple.com/reference/mapkit/mkmapviewdelegate/1452045-mapview

【讨论】:

谢谢马特,我遇到了类似的问题,Xcode Swift 3 转换器似乎错误地将我的 Swift 2 代码转换为 func mapView(mapView: MKMapView, viewFor annotation: MKAnnotation) -&gt; MKAnnotationView? @Eugene 是的,转换器不是 100% 可靠的,可选的协议方法是它可能行为不端的主要地方之一。很大程度上取决于您声明此视图控制器是 MKMapViewDelegate 的确切位置。 非常感谢!这个答案是无价的! @马特 我怎样才能给你100个赞?惊人的。浪费了 5 个小时。【参考方案2】:

如果其他人在使用正确签名时遇到同样的问题,请确保您已设置 mapView 委托:

override func viewDidLoad() 
    super.viewDidLoad()

    mapView.delegate = self

【讨论】:

以上是关于Swift 3 中未调用 ViewForAnnotation的主要内容,如果未能解决你的问题,请参考以下文章

Swift 3 / Xcode 8 beta 6 中未调用 UIApplicationShortcutItem 的 AppDelegate 函数

使用 iOS 和 Swift 3 在委托方法中未接收到 xmpp 存在

在 Swift4 中未调用 forwardingTarget

从 Objc 超类继承的 Swift 子类中未调用 viewDidLoad

Swift 中未调用 UICollectionView DidDeselectItemAtIndexPath 方法

Swift:在自定义视图中未调用 UIButton 触摸事件