How to add If statement before unwinding segue? [duplicate] - ios

This question already has answers here:
how to perform Condition check, before segue unwind
(2 answers)
Closed 5 years ago.
I have 2 views: FirstView and SecondView.
On SecondView, there are a textfield and a Submit button.
If user click Submit button, check if textfield is empty or not before going back to FirstView.
On StoryBoard of SecondView, I create a Unwind Segue by hold Ctrl and click on Submit button, then drag to Exit and choose tapToBackToFirstView
On FirstViewController:
#IBAction func tapToBackToFirstView (segue: UIStoryboardSegue) {
}
On SecondViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "backToFirstViewFromSecondView" {
let destinationController = segue.destination as! FirstViewController
destinationController.resultLabel.text = secondViewTextField.Text
}
}
From my code, If I click on Submit button, it always go to FirstView.
How can I add a IF statement to check if the textfield is empty or not? If it is empty, show an alert and DO NOT go to FirstView.
If it is not empty, go to FirstView.
Thanks

On your FirstView Controller you have unwindseguemethod tapToBackToFirstView which is connected from button action right?. Now remove that and instead of connecting unwind segue through IBAction, just drag from SecondViewController to it's own exit so that you will get one manual segue created. Give a segue identifier to this.
Now connection IBAction normally just like any button. call performSegueWithIdentifier in this based on condition.
#IBAction func tapToBackToFirstView(sender: AnyObject) {
if //Add your condition here
{performSegueWithIdentifier("segue identifier", sender: self)}
else {
//Do this
}
}

Related

performSegue creates two view controllers

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
self.delegate = segue.destination as? MenuViewController
print("check_1", self.delegate)
}
#IBAction func openMenu(_ sender: Any) {
performSegue(withIdentifier: "openMenu", sender: sender)
print("check_2", self.delegate)
}
My main ViewController updates values while MenuViewController displays these values. Each time ViewController values are updated, it calls self.delegate.updateValues in MenuViewController. I transition between the two ViewControllers through buttons.
My problem is that it seems like the MenuViewController displayed is a different object than the one stored in self.delegate inside ViewController. Printing the check statements:
check_1 Optional(<Menu.MenuViewController: 0x10161ca10>)
check_2 Optional(<Menu.MenuViewController: 0x10161ca10>)
check_1 Optional(<Menu.MenuViewController: 0x10161dd10>)
May I ask how do I make sure only one instance of MenuViewController is created and stored in self.delegate?
When you add a segue to a storyboard, if you hook up the segue to a specific button/IBAction, you don't need to call performSegue manually, it will be automatically called for you.
You have 2 segues executed, since both the storyboard executes the segue and then you also do it from code by calling performSegue.
performSegue should only be used when your segue isn't directly hooked up to a UI event or if you need to conditionally perform a segue - such as when you have a login button, where depending on the network response, you might execute an error or a login segue.

Perform action when segue is closed

I have a ViewController where I call segue to another ViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == blogSegueIdentifier {
let destination = segue.destination as! Reply
let path = tableView.indexPathForSelectedRow
let cell = tableView.cellForRow(at: path!) as! QuestionsTabCell
destination.blogName = String(cell.labelQues!.tag)
}
}
In the opened segue (ViewController) there is a UITextView and a send button in the UINavigationBar. So user inputs textView and sends it to server tapping on the button and after this opened segue (ViewController) closes and user returns to first ViewController. How to call a method in first ViewController when user closes segue without using viewWillAppear?
Hello #Mr Jo You can use unwind segue for this purpose.
declare a method in your first viewController Like :-
//MARK: - - Unwind Segue get data from select categories
#IBAction func unwindToAssignCatController(segue: UIStoryboardSegue) {
//get back data from selectcategory class
if segue.identifier == "segueIdentifier"{
let controller = segue.source as! Reply
// get your values from second viewController and use in first viewController
}
After that you have to select your second ViewController
1: right Click on Controller and drag on exit then below method will appear
2: Select it and assign an identifier to it.
3: then perform segue on that action where you want in second viewController with same identifier.
If you have the NavigationController, try: (Objective-C)
FirstVC* firstVC = self.navigationController.viewControllers[self.navigationController.viewControllers.count
- 2]
last but one in a series of viewControllers in the navigation stack
If you are opening the second viewController without the NavigationController, you can get the instance of the first viewController like:
FirstVC* firstVC = self.presentingViewController
Please not that the instance of the presenting VC will be available in this property after the transition will finish, in the viewDidAppear, for example

Swift: Keep segue from executing if condition not met

Currently I'm working on two different ViewControllers in my application, we can call them VC1 and VC2. VC1 displays a registration form, with a question in each row of a UITableView, and has an edit button. The edit button is as a segue from VC1 and VC2. VC2 displays an interface that will allow the user to edit the question. I want to write the application so that you cannot segue from VC1 to VC2 unless you have selected a question(row) to edit. Right now I have some of it set up, but it's possible that I have it backwards.
In VC1:
// this method isn't called until VC2 segues back to VC1... so I don't know how
// to make sure that a selection has been made before pressing the button
#IBAction func editQuestion(segue:UIStoryboardSegue) {
if let editQuestion = segue.sourceViewController as? VC2 {
}
}
In VC2:
override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject!) -> Bool {
// check to make sure that user has completed all fields of question
// if they haven't completed all fields, return false (do not segue)
// else segue to VC1
}
Implement in VC1:
override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {
if identifier == <your storyboard segue identifier> {
}
}
Give your storyboard segue an identifier, and then you can do the check in VC1, and return false if you do not want the segue to happen.

Swift - Unwind Segue triggering error

I am using for the first time the Unwind Segue approach. I have multiple view controllers as can be seen in the picture below (a few of them shown of course). In the Edit Profile I have a Done button. Once clicked I trigger an IBAction that triggers an unwind segue.
Here is the code for the Done button in the nav bar:
#IBAction func unwindToMainViews(sender: UIStoryboardSegue) {
//let sourceViewController = sender.sourceViewController
self.performSegueWithIdentifier("unwindToMainSegue", sender: self)
}
and in the
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!)
I am doing the following to pass data from Edit Profile back to Home View
if (segue.identifier == "unwindToMainSegue") {
// pass data to next view
let tabCtrl = segue.destinationViewController as! UITabBarController
let destinationVC = tabCtrl.viewControllers![0] as! HomeViewController
destinationVC.userObject = self.userObject;
}
When segue identifier is matched and code is executed (to transfer userObject from this controller to another), it triggers the error:
Could not cast value of type 'app.EditProfileViewController' (0x100b99d80) to 'UITabBarController' (0x104a1d030).
How can this error be fixed? I am surprised since i am casting to UITabBarController so thought it should work.
You don't return to the UITabBarController in an unwind segue. You return to the ViewController that triggered the original segue, or one if its ancestors.
As #jlehr stated in the comments:
Unwind segues don't return to anything; they dismiss any pushed and
presented view controllers between the source and destination view
controller. The destination is wherever the implementation of the
unwind method is found, regardless of how the source view controller
was presented.
To unwind to the viewController that triggered the original segue, you need to implement the #IBAction func returnToHere(segue: UIStoryboardSegue) function in the viewController you want to return to.
Then when you set up your Done button by dragging to the Exit icon, you select returnToHere from the pop-up.
To pass data back to the sourceViewController, give your unwind segue an identifier such as "unwindToSource", then override prepareForSegue in the viewController you are returning from:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "unwindToSource" {
let dvc = segue.destinationViewController as! SourceViewController
dvc.userObject = self.userObject
}
}

Segue not loading although there is no error or no crash or freeze

I come here with a very very strange error.
I have 3 View controllers in my storyboard.
1) Main Page with list of products ViewController
2) Single Product Detail ProductViewController
3) Barcode scanner BarcodeViewController
In the MAIN and PRODUCT DETAIL ViewController, i have a button saying "Scan Barcode" on top.
I first coded the button of "Scan Barcode" in the ViewController and segue it to the BarcodeViewController. It works perfectly.
For the same Scan Button in ProductViewController, i coded it differently.
I drag the button to EXIT. So that the ViewController loads again and as soon as it is loaded i programmatically load the Barcode scanner.
It does not work.
There is no error, there is no crash, nothing. Even Prepare for segue function is called. It goes into the right block everywhere.
Just the BarcodeViewController dont show up.
The code in ViewController
#IBAction func returned (segue: UIStoryboardSegue) {
NSLog("Returned Segue \(segue.identifier)")
if ( segue.identifier == "unwindToMainViewViaBarcode" )
{
dispatch_async(dispatch_get_main_queue(), {
self.performSegueWithIdentifier(self.segueIdentifierForBarcode, sender: nil)
});
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
NSLog("PrepareForSegue \(segue.identifier)")
if ( segue.identifier == segueIdentifierForBarcode )
{
// Reset barcode String
barcodeString = ""
// get reference for ViewController and set as a var
let destination = segue.destinationViewController as! BarcodeViewController
destination.mainView = self;
print("open barcode called")
}
}
U can refer so some answer in this SO Answer
Basically make a BOOL before perform unwind segue and check it at ViewDidAppear, if its set then perform segue from there and turn the BOOL to false
I found the problem.
In other projects it is working because I am showing segue Modally
Here i by mistake was just showing it.
Now that i have changed it to show as Modal
It is working fine.

Resources