Jade Reynolds
Jade Reynolds

Reputation: 301

Data not being passed through Segue

I have a slightly confusing issue, I am trying to send location data from a tableview through to a mapkit. My tableview loads the various bits of info to list the names of the location, when I click a cell it segues into a navigation view with the data, however it doesnt seem to be sending the data and errors with found nil issue. I did have this same tableview segueing to a different controller and it worked without issue.

This is my prepareForSegue on my main Viewcontroller

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "mapLocation" {
        if let detailsVC = segue.destination as? mapLocation {
            if let tr = sender as? newTracks {
                detailsVC.track = tr
            }
        }
    }
}

This is the mapkit view to segue to

import UIKit
import MapKit
import CoreLocation

class mapLocation: UIViewController, MKMapViewDelegate {


@IBOutlet weak var mapView: MKMapView!

var track: newTracks!

override func viewDidLoad() {
    super.viewDidLoad()

    let sourceloaction = CLLocationCoordinate2D(latitude: track.lat, longitude: track.lon)
    let destinationLocation = CLLocationCoordinate2D(latitude: track.lat, longitude: track.lon)

    let sourcePlacemark = MKPlacemark(coordinate: sourceloaction, addressDictionary: nil)
    let destinationPlacemark = MKPlacemark(coordinate: destinationLocation, addressDictionary: nil)

    let sourceMapItem = MKMapItem(placemark: sourcePlacemark)
    let destinationMapItem = MKMapItem(placemark: destinationPlacemark)

    let sourceAnnotation = MKPointAnnotation()
    sourceAnnotation.title = track.name

    if let location = sourcePlacemark.location {
        sourceAnnotation.coordinate = location.coordinate
    }

    let destinationAnnotation = MKPointAnnotation()
    destinationAnnotation.title = track.name

    if let location = destinationPlacemark.location {
        destinationAnnotation.coordinate = location.coordinate
    }

    self.mapView.showAnnotations([sourceAnnotation,destinationAnnotation], animated: true)

    let directionRequest = MKDirectionsRequest()
    directionRequest.source = sourceMapItem
    directionRequest.destination = destinationMapItem
    directionRequest.transportType = .automobile

    let directions = MKDirections(request: directionRequest)

    directions.calculate {
        (response, error) -> Void in

        guard let response = response else {
            if let error = error {
                print("Error: \(error)")
            }
            return
        }

        let route = response.routes[0]
        self.mapView.add((route.polyline), level: MKOverlayLevel.aboveRoads)

        let rect = route.polyline.boundingMapRect
        self.mapView.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
    }


}


func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) ->     MKOverlayRenderer {
    let renderer = MKPolylineRenderer(overlay: overlay)
    renderer.strokeColor = UIColor.red
    renderer.lineWidth = 4.0

    return renderer
}



}

and this is my NewTracks struct where the data is loaded to/from:

import Foundation
import FirebaseDatabase

struct newTracks {


let name: String!
let trackId: Int!
let postcode: String!
let trackType: String!
let locID: Int!
let lat: Double!
let lon: Double!
let phoneNumber: String!
let email: String!
let rating: Double!
let numrating: Double!
let totalrating: Double!
let ref: FIRDatabaseReference?



init(name: String, trackId: Int, postcode: String, trackType: String, trackURL: String, locID: Int, lat: Double, lon: Double, phoneNumber: String, email: String, rating: Double, numrating: Double, totalrating: Double) {
    self.name = name
    self.trackId = trackId
    self.ref = nil
    self.postcode = postcode
    self.trackType = trackType
    self.locID = locID
    self.lat = lat
    self.lon = lon
    self.phoneNumber = phoneNumber
    self.email = email
    self.rating = rating
    self.numrating = numrating
    self.totalrating = totalrating

}

init(snapshot: FIRDataSnapshot) {
    let snapshotValue = snapshot.value as! [String: AnyObject]
    name = snapshotValue["name"] as! String
    trackId = snapshotValue["id"]as! Int
    postcode = snapshotValue["postcode"]as! String
    trackType = snapshotValue["type"]as! String
    locID = snapshotValue["locID"]as! Int
    lat = snapshotValue["lat"]as! Double
    lon = snapshotValue["long"]as! Double
    phoneNumber = snapshotValue["phone"]as! String
    email = snapshotValue["email"]as! String
    rating = snapshotValue["rating"]as! Double
    ref = snapshot.ref
    numrating = snapshotValue["numrating"] as! Double
    totalrating = snapshotValue["totalrating"] as! Double

}

func toAnyObject() -> Any {
    return [
        "name": name,
        "trackId": trackId,
        "postcode": postcode,
        "trackType": trackType,
        "locID": locID,
        "lat": lat,
        "lon": lon,
        "phoneNumber": phoneNumber,
        "email": email,
        "rating": rating,
        "numrating": numrating,
        "totalrating": totalrating
            ]
}

}

The error happens on the line in the mapLocation VC

let sourceloaction = CLLocationCoordinate2D(latitude: track.lat, longitude: track.lon)

the lat and lon values are not being passed for some reason.

On my previous VC that the segue worked fine with the data all I had to do was to add the

var track: newTracks

and this allowed the communication to happen back to where the data is coming from, but for some reason it doesn't appear to be working now. I know it will be something fundamentally simple I have missed.

This is my original segue code that worked to a normal View COntroller, not a UINavigationController

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "TrackDetailVC" {
        if let detailsVC = segue.destination as? TrackDetailVC {
            if let tr = sender as? newTracks {
                detailsVC.track = tr
            }
        }
    }
}

Upvotes: 1

Views: 779

Answers (2)

Magnas
Magnas

Reputation: 4063

Yes, when your viewController is embedded in a UINavigationController you have to work through the parts of the chain until you get to the controller you want. Something like this should work:

override function prepare(for segue: UIStoryBoardSegue, sender: Any?) {
   if segue.identifier == “TrackDetailVC” {
       if let nav = segue.destinationVC as? UINavigationController {
           if let detailsVC = nav.viewControllers[0] as? TrackDetailVC {
               if let tr = sender as? newTracks {
                   detailsVC.track = tr
               }
           }
       }
   }
}

Upvotes: 2

Gabe Spound
Gabe Spound

Reputation: 590

sender can't conform to type newTracks. Do some debugging with breakpoints and maybe see why this cast isn't working. Try making a variable called newTracks and explicityly giving it a type, and set it equal to what you want. Then make detailsVc.track = newTracks

Upvotes: 0

Related Questions