Search code examples
iosswiftsprite-kitmapkitmkmapview

Swift MKMapView returning nil in GameScene


I'm currently experimenting with MapKit and SpriteKit, however I have run into a problem.

When I try to convert map coordinates to a point on my screen (in my GameScene), I get an error: Unexpectedly found nil while unwrapping an optional value

The following code produces the error and is in a function that (for testing purposes) runs when the screen is tapped. monster.position = (mapView?.convert(spawnLocation, toPointTo: view))!

monster is an SKSpriteNode declared at the top of my GameScene. spawnLocation is just a set of coordinates (I checked and they should be visible on the screen). mapView is declared at the top of my GameScene like so: var mapView = GameViewController().map (I believe my problem is here)

Checking if mapView contains a value or not results in nothing being printed to the console:

if (mapView != nil) {
        print("not nil")
        monster.position = (mapView?.convert(spawnLocation, toPointTo: view))!
}

My map shows up when I run the app, however nothing happens when the above code is executed. I think my problem is with the way I am currently accessing the map from the GameViewController, but I'm not sure how to fix it.

To clarify: my map is declared in my GameViewController and I need to access it from my GameScene so that I can convert the coordinates to a point in the view.

NOTE: I may just be using the convert function wrong.

GameViewController:

@IBOutlet var parentView: UIView!
@IBOutlet var map: MKMapView!
@IBOutlet var skview: SKView!

let locationManager = CLLocationManager()

override func viewDidLoad() {
    super.viewDidLoad()

    map.delegate = self
    map.showsScale = false
    map.showsPointsOfInterest = false
    map.showsUserLocation = true
    map.showsBuildings = true
    map.isZoomEnabled = false
    map.isScrollEnabled = false
    map.isPitchEnabled = false
    map.isRotateEnabled = false

    locationManager.requestWhenInUseAuthorization()
    if (CLLocationManager.locationServicesEnabled()) {

        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.startUpdatingLocation()

    }

    let region = MKCoordinateRegionMakeWithDistance((locationManager.location?.coordinate)!, 400, 400)
    map.setRegion(region, animated: false)

    parentView.addSubview(map)
    parentView.addSubview(skview)

    GIDSignIn.sharedInstance().uiDelegate = self

}

Solution

  • So after continuing to work on my issue, I took another look at this question (I had already tried the solution in the answer - it didn't work). I noticed that my problem might be that the scene in which I was trying to access the MKMapView/GameViewController from wasn't the first scene. When I added the following to my code, it printed nil:

    print("view controller", self.gameViewController)
    

    I then looked at the code responsible for transitioning from the first scene to the one I was having issues with, and I added a line:

    let signedInTransition = SKTransition.fade(withDuration: 1)
    
    let nextScene = GameScene(size: scene!.size)
    nextScene.scaleMode = .aspectFill
    
    nextScene.gameViewController = self.gameViewController /* ADDED THIS LINE */
    
    scene?.view?.presentScene(nextScene, transition: signedInTransition)
    

    Turns out my problem was that my scene didn't actually have a GameViewController and therefore

    let gameViewController:GameViewController!
    

    never actually contained a value.