How to pass data from ViewController3 to ViewController1 - ios

I am new to Swift and was wondering on how to pass data from ViewController to ViewController that isn’t connected by segue. I have spend 2 hours on this and still can’t figure a way to do it.
Edit: The problem that I am confused on is How to take out all the stacked ViewController expect the root ViewController while being able to pass data back to the first ViewController from ViewController3 with
'navigationController?.popToRootViewController(animated: false)'
class ViewController: UIViewController, nameDelegate {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var textfield1: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
label1.text = "Name"
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc2 = segue.destination as! ViewController2
vc2.middleOfTransferingName = textfield1.text!
}
#IBAction func buttonPressed1(_ sender: Any) {
performSegue(withIdentifier: "go2", sender: self)
}
func nameThatWasEntered(name: String) {
label1.text = name
}
}
class ViewController2: UIViewController, nameDelegate {
var middleOfTransferingName: String = ""
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc3 = segue.destination as! ViewController3
vc3.transferedWithSegueLabelText = middleOfTransferingName
vc3.namePassBack = self
}
#IBAction func buttonPressed2(_ sender: Any) {
performSegue(withIdentifier: "go3", sender: self)
}
func nameThatWasEntered(name: String) {
}
}
protocol nameDelegate {
func nameThatWasEntered(name: String)
}
class ViewController3: UIViewController {
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var textfield3: UITextField!
var transferedWithSegueLabelText: String = ""
var namePassBack: nameDelegate?
override func viewDidLoad() {
super.viewDidLoad()
label3.text = transferedWithSegueLabelText
}
#IBAction func buttonPressed3(_ sender: Any) {
namePassBack!.nameThatWasEntered(name: textfield3.text!)
navigationController?.popToRootViewController(animated: false)
}
}

I found the way to transfer ViewController3 data to ViewController!
var vc3 = ViewController3()
then making ViewController as the delegate of vc3 upon loading.
override func viewDidLoad() {
super.viewDidLoad()
vc3.namePassBack = self
}
Then going back to ViewController3, I add ""vc3."" before using the delegate.
#IBAction func buttonPressed3(_ sender: Any) {
vc3.namePassBack!.nameThatWasEntered(name: textfield3.text!)
navigationController?.popToRootViewController(animated: false)
}

if you use segue then use 'Unwind segue'
for this write given code in your 'A view controller'
#IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
}
In B_viewcontroller, On press button call 'Unwind segue'.
Note:- With the help of Unwind segue you can send the value for 3ed vc to 1se vc same as you send value form 1st vc to 2nd vc
for more go to this link

Related

Using segues to pass data in Swift?

I am trying to use segues to pass the data entered in the partyID text field to the partyID label in a separate view controller. However, I am getting errors in my code.
class PartyViewController: UIViewController {
// CALLS LOGIN VC
var LoginViewController: LoginViewController?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBOutlet weak var partyID: UITextField!
var token = String()
#IBAction func startParty(_ sender: UIButton) {
self.performSegue(withIdentifier: "partyVCtoGuestPartyVC", sender: self)
performSegue(withIdentifier: "hostStartParty", sender: self)
//LoginViewController?.fetchSpotifyProfile(accessToken )
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "partyVCtoGuestPartyVC"){
let GuestPartyVC = segue.destination as! GuestPartyViewController
GuestPartyVC.partyID = partyID.text
}
And here is the view controller I am trying to pass the data to:
class GuestPartyViewController: UIViewController {
#IBOutlet weak var partyID: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
partyIDLabel.text = partyID
// Do any additional setup after loading the view.
}
I get errors in my override func in LoginVC and then in the partyIDlabel.text in the GuestPartyVC.
In GuestPartyViewController
class GuestPartyViewController: UIViewController {
#IBOutlet weak var partyIDLabel: UILabel!
var partyID: String?
override func viewDidLoad() {
super.viewDidLoad()
partyIDLabel.text = partyID ?? ""
}
}
In PartyViewController
class PartyViewController: UIViewController {
#IBOutlet weak var partyID: UITextField!
#IBAction func startParty(_ sender: UIButton) {
self.performSegue(withIdentifier: "partyVCtoGuestPartyVC", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "partyVCtoGuestPartyVC",
let GuestPartyVC = segue.destination as? GuestPartyViewController {
GuestPartyVC.partyID = partyID.text
}
}
}
The IBOutlet is weak and may not be instantiate when you pass the text.
Could you try to pass the text in a property, then assign it in the viewDidLoad ?
class GuestPartyViewController: UIViewController {
#IBOutlet weak var partyID: UILabel!
var passedText: String?
override func viewDidLoad() {
super.viewDidLoad()
if let unwrappedPassedText = passedText {
partyIDLabel.text = partyID
}
}
// In the other controller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "partyVCtoGuestPartyVC") {
let GuestPartyVC = segue.destination as! GuestPartyViewController
GuestPartyVC.passedText = partyID.text
}
first change the call of login VC
var LoginViewController = LoginViewController()
then put this before the view did load method
#IBOutlet weak var partyID: UITextField!
and can you send the error that you get

How to pass Data from the SearchBar to UILabel?

how do you pass data from search Bar to UILabel in a different view controller
Passing Data between View Controllers
I have tried multiple questions here on stack, but it just doesn't work or the simulator ends up crashing for me
class FirstVC: UIViewController, DataEnteredDelegate {
#IBOutlet weak var label: UILabel!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showSecondViewController" {
let secondViewController = segue.destination as! SecondVC
secondViewController.delegate = self
}
}
func userDidEnterInformation(info: String) {
label.text = info
}
}
// protocol used for sending data back
protocol DataEnteredDelegate: class {
func userDidEnterInformation(info: String)
}
class SecondVC: UIViewController {
// making this a weak variable so that it won't create a strong reference cycle
weak var delegate: DataEnteredDelegate? = nil
#IBOutlet weak var searchBar: UISearchBar!
#IBAction func sendTextBackButton(sender: AnyObject) {
// call this method on whichever class implements our delegate protocol
delegate?.userDidEnterInformation(info: searchBar.text!)
// go back to the previous view controller
_ = self.navigationController?.popViewController(animated: true)
}
}
I don't find anything suspicious in your code which cause app crash. Meanwhile for data transfer between view controller we can use delegation and NotificationCenter. Below code uses NotificationCenter
let kStringTransfer = "StringTransferNotification"
class FirstViewController: UIViewController, DataEnteredDelegate {
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(setString(notify:)), name: NSNotification.Name(rawValue: kStringTransfer), object: nil)
}
func getSecondVC() {
if let second = self.storyboard?.instantiateViewController(withIdentifier: "Second") as? ViewController {
self.navigationController?.pushViewController(second, animated: true)
}
}
#IBAction func searchBarBtn(_ sender: Any) {
//go to search view controller
getSecondVC()
}
#objc func setString(notify: Notification) {
//set search bar string to text field
textField.text = notify.object as? String
}
}
class SecondViewController: UIViewController, UISearchBarDelegate {
#IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
searchBar.delegate = self
}
#IBAction func goBackBtn(_ sender: Any) {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: kStringTransfer), object: searchBar.text)
self.navigationController?.popViewController(animated: true)
}
}
When I need pass just small values between 2 viewControllers, I don't use a delegate, just create a variable in second view and pass like this.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "showView") {
let vc = segue.destination as! secondViewController
vc.stringTemp = "My string"
}
}

store segued data on a separate viewcontroller (swift4)

My code takes text from a textfield and segues to a separate view controller. The problem is that it can only store 1 segue entry. The new one replace the old every time the button is pressed. How on vc2 can I store every new entry to the segue.
VC
import UIKit
class ViewController: UIViewController {
#IBOutlet var txt: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func pressButton(_ sender: Any) {
if txt.text != "" {
performSegue(withIdentifier: "segue", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let secondController = segue.destination as! twoViewController
secondController.myString = txt.text!
}
}
twoVC
import UIKit
class twoViewController: UIViewController {
#IBOutlet var labelSmtih: UILabel!
var myString = String()
override func viewDidLoad() {
super.viewDidLoad()
labelSmtih.text = myString
}
}
If the second view controller is a UISplitViewController for example you should be able to append the text of the button to the label, by doing something in the lines of:
#IBAction func pressButton(_ sender: Any) {
if txt.text != "" {
performSegue(withIdentifier: "segue", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let secondController = segue.destination as! twoViewController
secondController.myString += txt.text!
}
}
If you really have a separated view controller it will probably lose the data once you go back to the first VC. In that case, I suggest you save the current text of the label on viewWillDisappear of the 2nd VC and then retrieve this on the prepareforsegue function on the first VC. More info here: Swift: How to store user preferences?

Send a string from a viewController to another one

Please, before you mark this question as duplicate, I want to know why my code is failing, not to be send to another one that is working.
I am a newbie in swift and I would like to send a variable "um_words" (which is calculated when a button is clicked) from a viewController when the same button is clicked, save that variable in the secondViewController and show it in a textView. To do so I have tried with many modifications of this code, which is giving no errors in the console but not showing the value of the variable on the textView:
1st VC
import UIKit
import Foundation
class TransViewController: UIViewController {
#IBOutlet var trad_text: UITextView!
#IBOutlet var buttonTrad: UIButton!
#IBOutlet var labelsitoh: UILabel!
var num_words = 0
#IBAction func butCalc(_ sender: UIButton) {
let text = trad_text.text
num_words = (text?.components(separatedBy: " ").count)!-1
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var DestViewController : PaymentViewController = segue.destination as! PaymentViewController
DestViewController.num_words = String(num_words)
}
}
override func viewDidLoad() {
super.viewDidLoad()
trad_text!.layer.borderWidth = 1
trad_text!.layer.cornerRadius = 20
trad_text!.layer.borderColor = UIColor(red:0.22, green:0.26, blue:0.39, alpha:1.0).cgColor
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
2nd VC
import UIKit
import Foundation
class PaymentViewController: UIViewController {
#IBOutlet var labelImport: UITextView!
var num_words = String()
override func viewDidLoad() {
super.viewDidLoad()
labelImport.text = num_words
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I have ab hypothesis of why it is not working: the function "prepare" is not being called; it only goes to next VC when the button is clicked...
Thank you for your time.
The func prepare should be outside of the button action, it will be called when segue is triggered.
#IBAction func butCalc(_ sender: UIButton) {
let text = trad_text.text
num_words = (text?.components(separatedBy: " ").count)!-1
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var DestViewController : PaymentViewController = segue.destination as! PaymentViewController
DestViewController.num_words = String(num_words)
}
See:
IBAction func butCalc(_ sender: UIButton) {
let text = trad_text.text
num_words = (text?.components(separatedBy: " ").count)!-1
self.performSegue(withIdentifier: "yourSegueIdentifier", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "yourSegueIdentifier") {
var destViewController : PaymentViewController = segue.destination as! PaymentViewController
destViewController.num_words = String(num_words)
}
}
You have create a function in another function...
Please try this.
PS: I did not test this code

View Controller delegate returns nil

My code is below. When I press the 'Done' or 'Cancel' buttons, it doesn't work as I want. I did some debugging, and delegate is nil even though I set it. Please help - thanks.
class ViewController: UIViewController,EditViewControllerDelegate {
#IBOutlet weak var label: UILabel!
//页面跳转时
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "EditView" {
//通过seque的标识获得跳转目标
let controller = segue.destinationViewController as! EditViewController
//设置代理
controller.delegate = self
//将值传递给新页面
controller.oldInfo = label.text
}
}
func editInfo(controller:EditViewController, newInfo:String){
label.text = newInfo
//关闭编辑页面
controller.presentingViewController!.dismissViewControllerAnimated(true, completion: nil)
}
func editInfoDidCancer(controller:EditViewController){
//关闭编辑页面
controller.presentingViewController!.dismissViewControllerAnimated(true, completion: nil)
}
}
import UIKit
protocol EditViewControllerDelegate {
func editInfo(controller:EditViewController, newInfo:String)
func editInfoDidCancer(controller:EditViewController)
}
class EditViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
var delegate:EditViewControllerDelegate?
var oldInfo:String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if oldInfo != nil{
textField.text = oldInfo
}
}
#IBAction func done(sender: AnyObject) {
delegate?.editInfo(self, newInfo: textField.text!)
}
#IBAction func cancel(sender: AnyObject) {
delegate?.editInfoDidCancer(self)
}
}
Try this,
class ViewController: UIViewController,EditViewControllerDelegate {
var controller: EditViewController?
#IBOutlet weak var label: UILabel!
//页面跳转时
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "EditView" {
//通过seque的标识获得跳转目标
controller = segue.destinationViewController as! EditViewController
//设置代理
controller.delegate = self
//将值传递给新页面
controller.oldInfo = label.text
}
}
func editInfo(controller:EditViewController, newInfo:String){
label.text = newInfo
//关闭编辑页面
controller.presentingViewController!.dismissViewControllerAnimated(true, completion: nil)
}
func editInfoDidCancer(controller:EditViewController){
//关闭编辑页面
controller.presentingViewController!.dismissViewControllerAnimated(true, completion: nil)
}
}
import UIKit
protocol EditViewControllerDelegate {
func editInfo(controller:EditViewController, newInfo:String)
func editInfoDidCancer(controller:EditViewController)
}
class EditViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
var delegate:EditViewControllerDelegate?
var oldInfo:String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if oldInfo != nil{
textField.text = oldInfo
}
}
#IBAction func done(sender: AnyObject) {
delegate?.editInfo(self, newInfo: textField.text!)
}
#IBAction func cancel(sender: AnyObject) {
delegate?.editInfoDidCancer(self)
}
}
I’m not able to tell from your code how you are handling the opening of EditViewController from your ViewController.
I’m guessing that your prepareForSegue:sender: is not getting called resulting in the delegate not getting set. To fix this, you will need to add a performSegueWithIdentifier:sender: call at the point where the segue needs to happen as in
self.performSegueWithIdentifier("EditView", sender: self)
You should replace whatever code is performing the opening of EditViewController with that call.
I have an app the uses showViewController:sender: to open up a second view controller from the first one even though there is a Show segue defined in my storyboard. The segue in my storyboard doesn’t get used in that case and prepareForSegue:sender: is never called as a result.
If I replace my
showViewController(myVC, sender: self)
with
performSegueWithIdentifier("mySegue", sender: self)
then prepareForSegue:sender: will get called. If I am setting a delegate, like you are, in prepareForSegue:sender:, the delegate will get set before the segue happens.

Resources