使用 unwind segue 传递数据
Passing data with unwind 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。我怎样才能只使用 unwind segue 而不是使用 delegate 来做到这一点。我是 swift 的新手,希望得到详细的解释。
我会这样做:
在视图控制器 1 中创建一个出口,如下所示:
@IBAction func unwindToViewController1(segue: UIStoryboardSegue) {
let foo = segue.sourceViewController.foo
// TODO: Use foo in view controller 1
}
连接视图控制器 2(vc 您正在从中展开),如下所示。从 vc2 中的黄色圆圈拖动到 'Exit'。来自视图控制器 1 的 IBAction 应该弹出。 Select它。
现在,无论何时从视图控制器 2 中退出,都会调用视图控制器 1 中的 unwindToViewController1:
方法。
这是您从视图控制器 2 中检索所需的 属性 的地方。请注意,您需要将 segue.sourceViewController
强制转换为您的自定义视图控制器子类,以便得到正确的 属性.
Øyvind Hauge 用相同的解决方案 方法 击败了我,但由于我已经开始提供更详细的答案,所以我也会添加它。
假设您的两个视图控制器命名如下:
- Master/entry点数:
ViewController
(vcA)
- 第二视图:
ViewControllerB
(vcB)
您从 (vcA) -> (vcB)
设置了 segue,正如您在示例中所做的那样
/* 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
}
}
接下来有点棘手的步骤是,使用此方法,用于将数据传回 from (vcB)
to[=71= 的 segue ] (vcA)
也 添加到 (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)
中的手动 Exit
segue 将 (vcB)
中的按钮连接到 (vcA)
中的此展开操作:
下面是将文本从 (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
委托仅用于 "locally" 改变 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
}
}
执行示例:
如果您的应用支持 iOS 9+,您可以像 prepareForSegue 一样传递数据,使用 UIStoryboardUnwindSegueSource that has a sender property which is exactly the same as the the sender
property in prepare(for segue: UIStoryboardSegue, sender: Any?)。
使用方法:
- 创建一个 unwindTo 方法。
注意:连接unwindTo方法与@Øyvind Hauge和@dfri在他们的回答中解释的相同
- 在您想要展开的视图控制器中,覆盖方法 canPerformUnwindSegueAction(_:from:withSender:)
- 在此方法中,检查类型
fromViewController
是否是您来自的类型
- 如果是,请将
sender
属性 转换为您发送的类型并且 return true
- 否则,return错误
代码片段(Swift 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
}
我创建了两个视图控制器。我创建了一个从第一个到第二个的 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。我怎样才能只使用 unwind segue 而不是使用 delegate 来做到这一点。我是 swift 的新手,希望得到详细的解释。
我会这样做:
在视图控制器 1 中创建一个出口,如下所示:
@IBAction func unwindToViewController1(segue: UIStoryboardSegue) { let foo = segue.sourceViewController.foo // TODO: Use foo in view controller 1 }
连接视图控制器 2(vc 您正在从中展开),如下所示。从 vc2 中的黄色圆圈拖动到 'Exit'。来自视图控制器 1 的 IBAction 应该弹出。 Select它。
现在,无论何时从视图控制器 2 中退出,都会调用视图控制器 1 中的
unwindToViewController1:
方法。这是您从视图控制器 2 中检索所需的 属性 的地方。请注意,您需要将
segue.sourceViewController
强制转换为您的自定义视图控制器子类,以便得到正确的 属性.
Øyvind Hauge 用相同的解决方案 方法 击败了我,但由于我已经开始提供更详细的答案,所以我也会添加它。
假设您的两个视图控制器命名如下:
- Master/entry点数:
ViewController
(vcA)
- 第二视图:
ViewControllerB
(vcB)
您从 (vcA) -> (vcB)
设置了 segue,正如您在示例中所做的那样
/* 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
}
}
接下来有点棘手的步骤是,使用此方法,用于将数据传回 from (vcB)
to[=71= 的 segue ] (vcA)
也 添加到 (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)
中的手动 Exit
segue 将 (vcB)
中的按钮连接到 (vcA)
中的此展开操作:
下面是将文本从 (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
委托仅用于 "locally" 改变 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
}
}
执行示例:
如果您的应用支持 iOS 9+,您可以像 prepareForSegue 一样传递数据,使用 UIStoryboardUnwindSegueSource that has a sender property which is exactly the same as the the sender
property in prepare(for segue: UIStoryboardSegue, sender: Any?)。
使用方法:
- 创建一个 unwindTo 方法。
注意:连接unwindTo方法与@Øyvind Hauge和@dfri在他们的回答中解释的相同
- 在您想要展开的视图控制器中,覆盖方法 canPerformUnwindSegueAction(_:from:withSender:)
- 在此方法中,检查类型
fromViewController
是否是您来自的类型 - 如果是,请将
sender
属性 转换为您发送的类型并且 return true - 否则,return错误
代码片段(Swift 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
}