swift 自定义地图 class

swift custom map class

我正在学习 Swift 并且想创建一个 MKMapKit 的子class 来封装一些特定的功能,比如检查两点之间的距离和创建自定义注释并将所有地图代码分离成一个class.

我创建了一个 class:

class GameMapViewController: MKMapView, MKMapViewDelegate{...}

我在主视图控制器的代码中启动了 class(并将其作为子视图添加到故事板上的视图中,以便我可以更轻松地控制它的位置):

gameMap = GameMapViewController(container: mapViewHolder)

这一切都设置好了,除了当我想从自定义注释触发 segue 时,一切正常:

func mapView(mapView: MKMapView!, didSelectAnnotationView view: MKAnnotationView!) {...}

当我点击注释标注时,didSelectAnnotationView 被调用,但没有我正在寻找的方法 performSegueWithIdentifier,所有 solutions to similar 问题都表明我应该使用....

(我尝试将 MapKit View 放到故事板上并将其 class 更改为使用 GameMapViewController 但是 none 初始化函数被触发)

我猜这与我初始化自定义设置的方式有关 class?

MainViewController.swift:

override func viewDidLoad() {
super.viewDidLoad()
....
// Create the game map
gameMap = GameMapViewController(container: mapViewHolder)
mapViewHolder.addSubview(gameMap)

...

}

GameMapViewController.swift:

import UIKit
import MapKit


class GameMapViewController: MKMapView, MKMapViewDelegate{

var spanQuestion:MKCoordinateSpan = MKCoordinateSpanMake(180, 180)
var spanAnswer:MKCoordinateSpan = MKCoordinateSpanMake(180, 180)
var hasUserCityLocationGuess: Bool = false

var containingView: UIView

override init(){
    println ("GameMapViewController init")
    containingView = UIView()
    super.init(frame: CGRect(x: 0, y: 0, width: 1000, height: 1000))

    self.delegate=self
    var latDeltaAnswer:CLLocationDegrees = 50
    var lngDeltaAnswer:CLLocationDegrees = 50
    spanAnswer = MKCoordinateSpanMake(latDeltaAnswer, lngDeltaAnswer)

    var latDeltaQuestion:CLLocationDegrees = 180
    var lngDeltaQuestion:CLLocationDegrees = 180
    spanQuestion = MKCoordinateSpanMake(latDeltaQuestion, lngDeltaQuestion)



}

required init(coder aDecoder: NSCoder) {
    containingView = UIView()
    super.init(coder: aDecoder)
    self.delegate = nil
    println ("GameMapViewController init with decoder")
}


convenience init(container: UIView) {
    println ("GameMapViewController convenience")
    self.init()
    self.delegate = self
    containingView = container


}

func mapViewDidFinishLoadingMap(mapView: MKMapView!) {
    println("mapViewDidFinishLoadingMap")
}

func mapViewWillStartLoadingMap(mapView: MKMapView!) {

    self.frame = CGRect (x: 0, y: 0, width: containingView.frame.width, height: containingView.frame.height)
    self.contentMode = UIViewContentMode.ScaleAspectFill
    superview?.sizeToFit()
    var guessPlaceRecognizer = UILongPressGestureRecognizer(target: self, action: "guessPlace:")
    guessPlaceRecognizer.minimumPressDuration = 1.0
    mapView.addGestureRecognizer(guessPlaceRecognizer)
    mapView.mapType = MKMapType.Satellite

}

func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
    if overlay is MKCircle {
        var circleRenderer = MKCircleRenderer(overlay: overlay)
        circleRenderer.strokeColor = UIColor.redColor()
        circleRenderer.fillColor = UIColor(red: 255, green: 0, blue: 0, alpha: 0.1)
        circleRenderer.lineWidth = 1
        //userOverlayCircleRender = circleRenderer
        return circleRenderer
    } else {
        return nil
    }
}

func guessPlace(gestureRecognizer:UIGestureRecognizer){

    let guessPlaceFirst = NSUserDefaults.standardUserDefaults().boolForKey("guess_place_preference")

    if guessPlaceFirst {
        var touchPoint = gestureRecognizer.locationInView(self)
        var newCoord:CLLocationCoordinate2D = self.convertPoint(touchPoint, toCoordinateFromView: self)
        var userAnnotation = UserPointAnnotation()
        userAnnotation.coordinate = newCoord
        self.addAnnotation(userAnnotation)


        var getLat: CLLocationDegrees = newCoord.latitude
        var getLon: CLLocationDegrees = newCoord.longitude
        var circleCenter: CLLocation =  CLLocation(latitude: getLat, longitude: getLon)
        addRadiusCircle(circleCenter)
        hasUserCityLocationGuess = true
    }

}

func showCity() {
    let location = CLLocationCoordinate2D(latitude: (currentCity["latitude"]! as CLLocationDegrees), longitude: (currentCity["longitude"]! as CLLocationDegrees))
    let region:MKCoordinateRegion = MKCoordinateRegionMake(location, self.spanAnswer)
    let city: String = currentCity["city"]! as String
    let conditions: String = currentCity["description"] as String
    let country: String = currentCity["country"]! as String
    let address = "\(city), \(country)"
    let cityAnnotation = CityPointAnnotation()

    cityAnnotation.title = address
    cityAnnotation.subtitle = "\(conditions)"
    cityAnnotation.coordinate = location


    self.setRegion(region, animated: true)
    self.addAnnotation(cityAnnotation)
    self.selectAnnotation(cityAnnotation, animated: true)


}

func cityInfoClick(sender:UIButton){
    //sender.performSegueWithIdentifier("segueCityWebView")
}




func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
    // Handle any custom annotations.

    if annotation is CityPointAnnotation {

        // Try to dequeue an existing pin view first.
        let reuseId = "CityPointAnnotationView"
        var annotationView = self.dequeueReusableAnnotationViewWithIdentifier(reuseId)
        if annotationView == nil {
            annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
            annotationView.image = UIImage(named: "marker.png")
            annotationView.rightCalloutAccessoryView = UIButton.buttonWithType(.InfoDark) as UIButton
            annotationView.canShowCallout = true
            return annotationView;

        } else {

            annotationView.annotation = annotation
        }

        return annotationView

    }
    return nil;
}

func mapView(mapView: MKMapView!, didSelectAnnotationView view: MKAnnotationView!) {
    println("didSelectAnnotationView")
}

func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) {
    println("calloutAccessoryControlTapped1")

    ///////////////////
    // I want to do a segue here
    // but nothing has the method performSegueWithIdentifier (self, mapView, control....)
    ///////////////////


}


func resetMap(){
    self.removeAnnotations(self.annotations)
    self.removeOverlays(self.overlays)
    var region:MKCoordinateRegion = MKCoordinateRegionMake(self.centerCoordinate, spanQuestion)
    self.setRegion(region, animated: true)
    hasUserCityLocationGuess = false

}
func addRadiusCircle(location: CLLocation){

    var radius = NSUserDefaults.standardUserDefaults().doubleForKey("guess_place_radius") as CLLocationDistance
    var circle = MKCircle(centerCoordinate: location.coordinate, radius: radius )

    self.removeOverlays(self.overlays)
    self.addOverlay(circle)


}

func doGeoCode( cityObject:PFObject ) -> Bool {
    ....
}

func userCityLocationGuess(userGuessTemp:Int)->NSDictionary {
    ....

}

}

这是因为您混淆了视图和视图控制器。你有一个视图(MKMapView 的子类,但你正在命名它并试图将它用作控制器。它也在做控制器的工作。

所以,你真的应该有一个视图控制器,它拥有并配置一个地图视图(普通 MKMapView),然后它可以与 segues 交互。