使用prepareForSegue传递对象的方法(Swift)

19

我想通过 prepareForSegue() 将一个对象传递到另一个场景。

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        // Get the new view controller using [segue destinationViewController].
        var nextScene =  segue.destinationViewController as! VehicleDetailsTableViewController

        // Pass the selected object to the new view controller.
        if let indexPath = self.tableView.indexPathForSelectedRow() {
            let selectedVehicle = vehicles[indexPath.row]
            nextScene.currentVehicle = selectedVehicle
        }
    }

我有一个currentVehicle对象来获取这些对象。但是,当我尝试运行时,它崩溃并出现关于向下转换(downcasting)的错误。

错误编辑

无法将类型为'XXX.DisplayViewController' (0x1082dcd80)的值强制转换为类型为'XXX.VehicleDetailsTableViewController' (0x1082dc9a0)。(lldb)


你真的应该检查segue标识符,以确保正确地转换destinationViewController。你具体收到了什么错误信息? - Abizern
请检查我的问题,已更新。 - Mehmet
看起来 segue.destinationViewController 给你的是 DisplayViewController。检查一下 storyboard 中的连接。 - KevinS
4个回答

50

在storyboard中为segue(比如说mySegue)设置一个标识符。

使用Xcode 10 swift 4.x(也适用于Xcode 9和8,swift 3.x)。

override func prepare(for segue: UIStoryboardSegue, sender: Any?){}

这是针对从您当前的UIViewController中调用的所有跳转请求。因此,标识符用于区分不同的跳转。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "mySegue" , 
       let nextScene = segue.destination as? VehicleDetailsTableViewController , 
       let indexPath = self.tableView.indexPathForSelectedRow {
        let selectedVehicle = vehicles[indexPath.row]
        nextScene.currentVehicle = selectedVehicle
    }
}

如果您正在使用Xcode 7,Swift 2.x

那么请使用以下代码:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "mySegue" {
    var nextScene =  segue.destinationViewController as! VehicleDetailsTableViewController

    // Pass the selected object to the new view controller.
    if let indexPath = self.tableView.indexPathForSelectedRow {
        let selectedVehicle = vehicles[indexPath.row]
        nextScene.currentVehicle = selectedVehicle
    }
  }
}

nextScene后设置一个断点,查看是否通过在TableView中点击任何单元格来触发它。如果没有触发,则 storyboard 中提供的标识符名称必须与此处提供的不同。


几乎成功了。在 secondScene 上,println(currentVehicle?.location) 返回 nil。我不明白为什么,通常它都有一个值,我无法传递。 - Mehmet
var nextScene 后面设置一个断点,查看是否在单击 TableView 中的任何单元格时触发它。如果没有触发,则故事板中提供的标识符名称必须与此处给出的名称不同。 - Raja Vikram

8

在Swift 3.0 Xcode 8 beta 6中

AnyObject 已被重命名为 Any?

override func prepare(for segue: UIStoryboardSegue, sender: Any?){
    let nextScene =  segue.destinationViewController as! VehicleDetailsTableViewController

    // Pass the selected object to the new view controller.
    if let indexPath = self.tableView.indexPathForSelectedRow {
        let selectedVehicle = vehicles[indexPath.row]
        nextScene.currentVehicle = selectedVehicle
    }
  }
}

2
值得注意的是,segue.destinationViewController 已经更名为 segue.destination。 - SeanA
这不是一个有效的答案...你没有检查segue.identifier...如果有多个segues,这将导致崩溃。 - Raja Vikram

3

在 Swift 3 和 Xcode 8 中

不要使用 "identifier"。我不知道为什么,但 "segue.identifier" 总是为空。我只是像这样使用 prepare 方法,它就可以工作了!

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let secondController = segue.destination as? SecondController {
        secondController.anyItemInSecondController = self.anyItemInFirstController
    }

2

这个错误提示你的是,segue.destinationViewController 不是一个 VehicleDetailsTableViewController。我们没有足够的细节来告诉你为什么。

检查你的 segues 并确保它们都指向正确的位置,在执行转换之前始终检查 segue 的标识符。

if segue.identifier == "theNameOfYourSegue" // then do your cast

我会使用 switch 语句而不是 if,但是没错。 - Abizern
@Abizern 我知道这已经很老了,但是,你有任何好的理由这样做吗? - iShaalan
@iShaalan 在存在多个选择的情况下,也就是标识符有多个可能的取值时,我发现switch语句更容易阅读。 - Abizern

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接