2016-02-10 162 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 
    }