2016-02-10 110 views
20

我创建了两个视图控制器。我从第一个到第二个创建了一个segue来传递数据。现在我想将数据从第二个视图控制器传递到第一个视图控制器。我经历了许多类似的问题,由于缺乏关于如何平仓的知识,我无法实现这些问题。传递数据展开segue

ViewController.swift

class ViewController: UIViewController 
{ 
    var dataRecieved: String? 
    @IBOutlet weak var labelOne: UILabel! 
    @IBAction func buttonOne(sender: UIButton) 
    { 
     performSegueWithIdentifier("viewNext", sender: self) 
    } 
    override func prepareForSegue(segue: (UIStoryboardSegue!), sender: AnyObject!) 
    { 

     var svc: viewControllerB = segue.destinationViewController as! viewControllerB 
     svc.dataPassed = labelOne.text 
    } 
} 

这将所述数据传递到在dataPassed视图控制器 “viewControllerB”。说,现在我想要将一些数据从viewControllerB传递到ViewController中的dataRecieved。我怎样才能做到这一点,只有放松segue而不是使用委托。我很快就会发现,希望能有详细的解释。

+0

只需在展开视图控制器中实现'prepareForSegue'并访问'destinationViewController',它将成为您展开的视图控制器。您可能会想要在故事板中提供展开顺序和标识符 – Paulw11

+0

它提供了一个错误“没有标识符”btnSubmitSegue“'”。我在视图控制器中添加了segue标识符。我只用一个segue来连接两个视图控制器。我相信放松segue只是回到它以前的视图控制器没有任何额外的赛段?你能详细解释一下吗?一些代码,将不胜感激:) – ebby94

+0

创建开卷SEGUE按往常一样 - 拖动到场景中的'exit'图标。现在,在左侧的对象检查器中,您将看到视图控制器,第一响应者和退出图标下方列出的展开顺序。您可以点击展开顺序并在右侧的检查器中给它一个标识符。 – Paulw11

回答

43

岛之风豪格打我相同的解决方案方法,但我已经有一个更详细的回答开始,我将添加它。


比方说,你的两个视图控制器命名如下:

  • 主/入口点:ViewController(vcA)
  • 次视点:ViewControllerB(vcB)

您建立SEGUE从(vcA) -> (vcB)开始,就像你在例子中做的那样

/* in ViewController.swift */ 

// ... 

// segue ViewController -> ViewControllerB 
override func prepareForSegue(segue: (UIStoryboardSegue!), sender: AnyObject!) 
{ 
    if segue.identifier == "viewNext" { 
     let viewControllerB = segue.destinationViewController as! ViewControllerB 
     viewControllerB.dataPassed = labelOne.text 
    } 
} 

的有些麻烦步骤接下来的是,使用该方法,用于传递数据返回(vcB)(vcA)的SEGUE是加入到(vcA)源,作为@IBAction方法(而比可能预期的要多,添加到(vcB)的来源)。

/* in ViewController.swift */ 

// ... 

// segue ViewControllerB -> ViewController 
@IBAction func unwindToThisView(sender: UIStoryboardSegue) { 
    if let sourceViewController = sender.sourceViewController as? ViewControllerB { 
     dataRecieved = sourceViewController.dataPassed 
    } 
} 

您其后(vcB)(vcA)能通过手动Exit SEGUE在(vcB)连接比方说,一个按钮来此开卷动作:

enter image description here

下面跟随从(vcA)传递文本的一个完整的例子(vcB); (可能)通过UITextField修改该文本,最后将可能修改的文本返回到(vcA)


(vcA)来源:

/* ViewController.swift: Initial view controller */ 
import UIKit 

class ViewController: UIViewController { 

    var dataRecieved: String? { 
     willSet { 
      labelOne.text = newValue 
     } 
    } 
    @IBOutlet weak var labelOne: UILabel! 

    @IBAction func buttonOne(sender: UIButton) { 
     performSegueWithIdentifier("viewNext", sender: self) 
    } 

    // set default labelOne text 
    override func viewDidLoad() { 
     super.viewDidLoad() 

     labelOne.text = "Default passed data" 
    } 

    // segue ViewController -> ViewControllerB 
    override func prepareForSegue(segue: (UIStoryboardSegue!), sender: AnyObject!) 
    { 
     if segue.identifier == "viewNext" { 
      let viewControllerB = segue.destinationViewController as! ViewControllerB 
      viewControllerB.dataPassed = labelOne.text 
     } 
    } 

    // segue ViewControllerB -> ViewController 
    @IBAction func unwindToThisView(sender: UIStoryboardSegue) { 
     if let sourceViewController = sender.sourceViewController as? ViewControllerB { 
      dataRecieved = sourceViewController.dataPassed 
     } 
    } 
} 

(vcB)源(注意,这里的UITextFieldDelegate代表仅用于“本地”变异的dataPassed属性的值,这将返回到(vcA)并分配给dataRecieved后者的属性)

/* ViewControllerB.swift */ 
import UIKit 

class ViewControllerB: UIViewController, UITextFieldDelegate { 

    var dataPassed : String? 
    @IBOutlet weak var textField: UITextField! 

    // set default textField text to the data passed from previous view. 
    override func viewDidLoad() { 
     super.viewDidLoad() 

     textField.text = dataPassed 

     // Handle the user input in the text field through delegate callbacks 
     textField.delegate = self 
    } 


    // UITextFieldDelegate 
    func textFieldShouldReturn(textField: UITextField) -> Bool { 
     // User finished typing (hit return): hide the keyboard. 
     textField.resignFirstResponder() 
     return true 
    } 

    func textFieldDidEndEditing(textField: UITextField) { 
     dataPassed = textField.text 
    } 
} 

执行示例:

enter image description here

+0

非常感谢您的详细解释!这有助于我更好地理解:) – ebby94

+0

也许它在我面前,但'willSet''newValue'是什么'labelOne.text = newValue }' –

+0

@DarkhorseFantasySports不用担心:它是新值的默认名称集:_“如果实现'willSet'观察者,它通过了新的属性值作为一个常量参数可以指定这个参数为你的'willSet'实现的一部分的名称。如果你不写参数名称。和你的实现中括号,参数提供与newValue'的'默认参数名“_ - 从[雨燕语言指南 - 属性](https://developer.apple.com/library/content/documentation/斯威夫特/概念/ Swift_Programming_Language/Properties.html)。 – dfri

7

这是我会怎么做:

  1. 创建视图控制器1的出口,就像这样:

    @IBAction func unwindToViewController1(segue: UIStoryboardSegue) { 
    
        let foo = segue.sourceViewController.foo 
    
        // TODO: Use foo in view controller 1 
    } 
    
  2. 连接视图控制器2(你是从退绕VC)如下所示。从vc2中的黄色圆圈拖动到“退出”。弹出视图控制器1的IBAction。选择它。 enter image description here

  3. 现在,每当你从视图控制器2放松,在视图控制器1 unwindToViewController1:方法被调用。

  4. 这是您将从视图控制器2中检索所需属性的位置。请注意,您需要将segue.sourceViewController转换为您的自定义视图控制器子类以获取正确的属性。

+0

谢谢!这回答我的问题:) – ebby94

+0

很高兴它的工作 –

0

如果您的应用支持的iOS 9+你可以通过数据几乎相同,prepareForSegue,用UIStoryboardUnwindSegueSource具有sender性质是完全一样的prepare(for segue: UIStoryboardSegue, sender: Any?)的的sender财产。

如何使用它:

  1. 创建unwindTo方法。

注:连接unwindTo方法是一样的@岛之风豪格和@dfri在他们的答案解释。

  • 里面你想放松到,覆盖的方法canPerformUnwindSegueAction(_:from:withSender:)
  • 在此方法中,检查是否类型fromViewController是你是从
  • 如果传来的类型视图控制器它,施放sender属性为您发送的类型和返回true
  • 否则,返回false
  • 代码剪断(雨燕4.0):

    @IBAction func unwindToMyFirstViewController(segue: UIStoryboardSegue) {} 
    
    override func canPerformUnwindSegueAction(_ action: Selector, from fromViewController: UIViewController, withSender sender: Any) -> Bool { 
        if fromViewController is MyCustomViewController, 
         let customType = sender as? MyCustomType { 
         return true 
        } 
        return false 
    }