数据未通过 Segue

Posted

技术标签:

【中文标题】数据未通过 Segue【英文标题】:Data not being passed through Segue 【发布时间】:2017-03-14 17:01:07 【问题描述】:

我有一个稍微令人困惑的问题,我正在尝试将位置数据从 tableview 发送到 mapkit。我的 tableview 加载各种信息以列出位置的名称,当我单击一个单元格时,它会进入带有数据的导航视图,但是它似乎没有发送数据和发现错误的 nil 问题。我确实有这个相同的 tableview 连接到不同的控制器,它没有问题。

这是我的主视图控制器上的 prepareForSegue

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
            
        
    

这是要转到的 mapkit 视图

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





这是我的 NewTracks 结构,数据被加载到/从:

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
            ]



错误发生在 mapLocation VC 中的行上

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

由于某种原因未传递 lat 和 lon 值。

在我之前的 VC 中,segue 可以很好地处理数据,我所要做的就是添加

var track: newTracks

这使得通信可以回到数据的来源,但由于某种原因,它现在似乎无法正常工作。我知道这将是我错过的基本简单的事情。

这是我的原始 segue 代码,适用于普通 View COntroller,而不是 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
            
        
    

【问题讨论】:

你能在detailsVC.track = tr 行的func prepare(for segue:) 方法中设置一个断点吗?如果断点没有停止代码执行,那么sender as? newTracks 必须为nil,并且问题早在准备segue 的数据。 另外,当您提到“使用数据进入导航视图”时,您的意思是目标 VC 嵌入在 UINavigationController 中吗?如果是这样,那么您的 segue 代码将需要考虑到它。 添加三个断点,它们会自动继续并简单地记录一条消息。他们都应该进入prepare(for segue: UIStoryboardSegue, sender: Any?)。它们应该以if let detailsVC… 开头连续三行。这将告诉您哪一步失败以及问题所在。也许 segue 名称拼写错误,也许目的地是导航控制器而不是您的 mapLocation 类,或者发件人不是 newTracks。 (顺便说一句:类应以大写字母开头,实例以小写字母开头。) 谢谢大家,我会试试这些。 @Magnas 是的,它是嵌入到 UINavigationController 中的 VC。我第一次用这个,有什么特别需要做的吗? 我已将我的原始 segue 代码添加到帖子底部。我所做的只是更改了 segue 的标识符和它指向的 VC 【参考方案1】:

是的,当您的 viewController 嵌入到 UINavigationController 中时,您必须遍历链的各个部分,直到找到您想要的控制器。像这样的东西应该可以工作:

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
               
           
       
   

【讨论】:

这很好用,谢谢。我没有意识到需要通过 UINavigationController 并直接进入我的嵌入式 VC。 不,我认为它有效,但我忘记了我已经为 lat 和 lon 设置了明确的值。当我将它设置回 track.lat 和 track.lon 时,它再次失败并出现“found nil”错误 您似乎遇到了两个问题。第一个是对 UINavigationController 的 segue 引用,我的回答显示了如何通过这种 segue 传递数据。第二个似乎与您提供数据的方式有关。你在哪里填充tr【参考方案2】:

发件人不能符合类型 newTracks。用断点做一些调试,也许看看为什么这个演员不起作用。尝试创建一个名为 newTracks 的变量并明确地给它一个类型,并将其设置为你想要的。然后制作detailsVc.track = newTracks

【讨论】:

但我没有得到的是,当我将相同的 segue 指向不同的 VC 时,它工作得很好,我所更改的只是 Segue ID,并将其指向一个新的 UINavigationController 我在帖子底部添加了我原来的 segue 代码。我所做的只是更改了 segue 的标识符和它指向的 VC 问题在于UINavigationControllersender的类型)不能符合newTracks类型。我不知道为什么,但这显然是正在发生的事情。尝试我在回答中提到的解决方案,它相当简单。如果您遇到问题,请告诉我。 试过了,创建了一个名为 nTracks 的新变量作为 Double。为其分配一个值 1.54333,然后设置 detailsVC = nTracks。这失败了“无法分配 Double 类型的值来键入 newTracks 因为 detailsVC 是 ViewController 类型而 nTracks 是 double 类型...您必须在 detailsVC 中创建一个 double 并执行 detailsVC.variable = ntracks

以上是关于数据未通过 Segue的主要内容,如果未能解决你的问题,请参考以下文章

为啥程序在登录时不执行segue?

通过 segue 在视图控制器之间传递数据

通过 navigationController 使用 segue 传递数据

通过 Segue 将数据传递给新的 ViewController

通过 unwind segue 传递数据

通过 segue 问题在 UITableView 和 UIViewController 之间推送数据