快速通过segue传递数组

Posted

技术标签:

【中文标题】快速通过segue传递数组【英文标题】:Passing array through segue in swift 【发布时间】:2015-10-12 21:15:29 【问题描述】:

几天来,我一直在努力使用 Swift 将数组从我的SecondViewController 传递给我的FirstViewController

根据我的研究,我发现 segueprepareForSegue 是一个可行的选择,但我似乎无法弄清楚。我做错了什么?

我在 SecondViewController 中的 prepareForSegue 如下所示:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
        var DVC: FirstViewController = segue.destinationViewController as! FirstViewController
        DVC.mySeguedArray = myIncomeArray

我的 FirstViewController 看起来像这样:

class FirstViewController: UIViewController 
@IBOutlet weak var textView: UITextView!
var myIncomeArray: [Income] = []
var mySeguedArray: [Income] = []

override func viewDidLoad() 
    super.viewDidLoad()
    myIncomeArray = mySeguedArray

另外值得一提的是,我确信我正在填充SecondViewController 中的数组,因为我正在通过在向其中添加新的Income 对象时打印出数组的大小来测试它。但是FirstViewController 中的数组在检查segue 之后的大小时只返回0

编辑:添加了故事板的图片 StoryBoard

【问题讨论】:

什么是启动segue回到第一个vc?并且您之间是否有导航控制器,或者它是一个显示细节 segue 还是其他什么? 我现在尝试在情节提要上按 ctrl + 拖动,从 SecondViewController 上的添加按钮上的添加按钮到我的 FirstViewController,但它只能让我推动、模态和自定义。 push 没问题,但请确保在属性检查器中输入正确的 segue id 在按钮和 FirstViewController 之间创建推送后出现以下错误。 *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Could not find a navigation controller for segue 'passArray'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.' 在导航控制器中嵌入第一个vc 【参考方案1】:

你知道 Swift 中的数组是值类型吗?因此,当您将数组分配给其他变量或将其传递给某个方法时,该值将被传递;不是对实际对象的引用。当您将数组传递给第二个视图控制器时,它会复制原始数组的内容。然后,您将添加到此数组中,它不会更改原始数组的内容。

我建议您从第二个视图控制器到第一个视图控制器创建某种回调或委托模式来通知更改,以便第一个视图控制器也将修改原始数组内容。

这里有一小部分代码可以帮助你理解这一点,

let originalArray = ["a", "b", "c"]

var newArray = originalArray

newArray.append("d")

print(originalArray) // prints ["a", "b", "c"]
print(newArray) // prints ["a", "b", "c", "d"]

【讨论】:

好的,明天我会调查的。但只要我每次 segue 时都可以覆盖数组,那么这不会成为问题,因为我的 FirstViewController 只是我想在 textView 中显示它们的地方。【参考方案2】:

您可以使用协议在视图控制器之间传递数据

protocol YourFirstViewControllerDelegate: class 
    func onButtonClicked(yourString: [String])

当您想要显示您的第一个视图控制器时,将数据从第一个视图控制器传递到主视图控制器中的第二个:

    您应该将主视图控制器设置为您的视图控制器委托yourFirstViewController.setDlegate(self)

    在 FirstViewController 中,您应该使用 onButtonClicked([String]) 将事件引发到 main

    在 onButtonClicked([String]) 中,您可以调用 secondViewController 并使用 onSecondViewController([String]) 传递您的数组

    class MainViewController: UIViewController,YourFirstViewControllerDelegate
    var yourString = [String]()
    weak var vcFirst: FirstViewController?
    weak var vcSecond: SecondViewController?
    func onFirstViewController()
    
        if (self.vcFirst == nil)
            self.vcFirst = self.storyboard?.instantiateViewController(withIdentifier: "FirstViewController") as? FirstViewController
            self.vcFirst!.view.translatesAutoresizingMaskIntoConstraints = false
            self.vcFirst?.setDelegate(youeFirstViewControllerDelegate: self)
        
        self.setActiveController(viewController: self.vcFirst)
    
    
    
    func onSecondViewController(yourString:[String])
        if (self.Second == nil)
            self.Second = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController
            self.vcSecond!.view.translatesAutoresizingMaskIntoConstraints = false
    self.vcSecond.setArray(yourArray: self.yourArray)
        
        self.setActiveController(viewController: self.vcSecond)
    
    
    
    ....// your view controller method
    
    func onButtonClicked(yourString: [String])
    self.yourString = yourString
    onSecondViewController(yourString:self.yourString)
    
    

在您的第一个视图控制器中

class FirstViewController: UIViewController
    weak var yourFirstViewControllerDelegate: YourFirstViewControllerDelegate?
    var yourString = ["test1","test2"]
//  all your overide method should be here
    func setDelegate(yourFirstViewControllerDelegate:  YourFirstViewControllerDelegate) 
    self.yourFirstViewControllerDelegate = yourFirstViewControllerDelegate
  

func onButtonClicked()
     self.yourFirstViewControllerDelegate.onButtonClicked(self.yourString)
    

在您的第二个视图控制器中

class SecondViewController: UIViewController
var yourString = [String]
//  all your overide method should be here and you can use your [String]
 func setArray(yourString:[String])
 self.yourString = yourString
 

我现在没有 Mac OS 来检查我的代码,请阅读这段代码,不要复制,我明天会编辑这段代码

【讨论】:

【参考方案3】:

您的代码看起来不错,请使用以下 prepareforsegue,因为它有助于找出问题所在

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
    if segue.identifier == "segueIdInStoryboard" 
        if let DVC = segue.destinationViewController as? FirstViewController
            DVC.mySeguedArray = myIncomeArray
         else 
            print("Data NOT Passed! destination vc is not set to firstVC")
        
     else  print("Id doesnt match with Storyboard segue Id") 


class FirstViewController: UIViewController 

     @IBOutlet weak var textView: UITextView!
     var myIncomeArray: [Income]!
     var mySeguedArray: [Income]!
         didSet
             myIncomeArray = mySeguedArray //no need to call viewDidLoad
         
     

【讨论】:

segue 的一切工作正常,但似乎每次我导航到 SecondViewController 时它都会创建一个新的空 myIncomeArray,但有一个例外,如果我按下 Back 按钮FirstViewController。然后它保留数据。 好的,我已经设法解决了这个问题。我也通过在FirstViewController 中实现 prepareForSegue 来做到这一点。所以我总是传递同一个数组而不是初始化一个新数组。谢谢大家的回答,我学到了很多!

以上是关于快速通过segue传递数组的主要内容,如果未能解决你的问题,请参考以下文章

将结果从 Swift 数组传递到 Segue 到描述

使用没有 segues 的协议将数组从 appDelegate 传递到 Viewcontroller

使用 segues 将 Parse 数组中的图像快速链接到 secondViewController

Segue 不会传递数据

快速在标签查看的控制器之间传递数据?

objectAtIndex 没有在 segue 中传递选定的行