I'm trying to make the segue from viewcontroller to 2ndviewcontroller only when my condition is met. I've connected the segue from the button in viewcontroller to the 2ndviewcontroller. So far I have:
#IBAction func switchView(_ sender: AnyObject) {
// if a and b's textfields aren't empty
if(!(a.text?.isEmpty)! && !(b.text?.isEmpty)!) {
a1 = a.text!;
b1 = b.text!;
}else{
// do something
}
}
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if(identifier == "2ndviewcontroller") {
if(!(a.text?.isEmpty)! && !(b.text?.isEmpty)!) {
return true
}
}
return false
}
With this, I've been able to make the segue ONLY when a and b's textfields are not empty. That's exactly what I want but I also want to pass data from viewcontroller to 2ndviewcontroller as well.
func prepForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "2ndviewcontroller" {
let 2ndviewcontroller = segue.destination as! 2ndviewcontroller
2ndviewcontroller.c = a
}
}
}
I used the code above to pass data from viewcontroller to 2ndviewcontroller. Problem is I don't know how to combine them to both pass data, AND only make the segue when condition is met. When I have both functions, the bool function executes correctly, but prepForSegue does not pass data. When I comment out the bool function, prepForSegue passes the data, but I'm cannot apply a condition for making the segue.
Edit: fixed by using prepareForSegue method provided in the comments below.
As discussed in the comments, the method name should be prepareForSegue, not prepForSegue.
Related
I am about to pass data from a ViewController going to another ViewController using segue. When checking the data(event) from a variable thru breakpoint in the 1st View Controller the data(event) is not nil. But when I checked the 2nd View Controller the data(event) is nil. I am confuse whether if the reason is, I have error in my codes or because of the error appeared in my console that says Unable to insert COPY_SEND. Hope I can get some help from you. Thank you
Segue from First View Controller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "DashBoardViewController" {
let dashBoardController = segue.destination as! DashBoardViewController
dashBoardController.self.event = event
dashBoardController.self.passcode = passcode
}
}
Event and Passcode Turns Nil
override func viewDidLoad() {
super.viewDidLoad()
guard event != nil, passcode != nil else {
_ = SCLAlertView(appearance: appearance).showError("No Event Details", subTitle: "There's no event details, please logout and try again")
return
}
showEventDetails()
}
showEventDetails
func showEventDetails() {
DispatchQueue.main.async{
self.eventNameLabel.text = "\(self.event.name.uppercased())"
self.locationLabel.text = "\(self.event.location.uppercased())"
if let dateStringFromDate = getFormattedStringFromDate(date: (self.event.startDateTime), formatString: "MMMM dd, yyyy/ hh:mm a") {
self.dateTimeLabel.text = dateStringFromDate
} else {
self.dateTimeLabel.text = "-"
}
}
}
I am assuming you linked the segue which goes to DashBoardViewController on your submitButton by Interface Builder, which means when you are tapping on the submit button, the #IBAction func submitButton(_ sender: UIButton) { } gets called, where you check if your passcode is good to go and if so you are calling validateEventPasscode() which calls an API endpoint (asynchronous) and only there you are populating the self.event = event (line 187 in ViewController.swift).
Now, what really happens is that when you link a segue from a button by IB (interface builder), there will be a perform segue internally which we have to stop by overriding the following method in ViewController.swift: source
func shouldPerformSegue(withIdentifier identifier: String,
sender: Any?) -> Bool {
return false
}
This way your call from line 190 - ViewController.swift:
self.performSegue(withIdentifier: "showEventDashboard", sender: self)
is the one that fires:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "DashBoardViewController" {
let dashBoardController = segue.destination as! DashBoardViewController
dashBoardController.event = event
dashBoardController.passcode = passcode
}
}
You can test my theory by placing three breakpoints in ViewController.swift:
line 134 at validateEventPasscode() from submitButton IBAction func;
line 190 at self.performSegue(withIdentifier: "showEventDashboard", sender: self) from validateEventPasscode() func;
line 108 at dashBoardController.event = event from prepare(for segue, sender) func;
Buggy order of execution: 1, 3, 2 - at the moment this I would expect if my theory is correct;
Desired order of execution: 1, 2, 3.
Long story short, you populate your self.event after you perfomSegue and go to the next screen, that's why your event is nil in the next VC.
I used as reference the ViewController.swift file from your repo: ViewController.swift
Hope it helps, cheers!
Replace your prepareForSegue method in FirstViewController with this
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "DashBoardViewController" {
let dashBoardController = segue.destination as! DashBoardViewController
dashBoardController.event = event
dashBoardController.passcode = passcode
}
}
you don't need to write
dashBoardController.self.event = event
dashBoardController.self.passcode = passcode
Just remove self from above two lines.
I want make a filter for search (on a separate screen) and I think about how to transfer data for my second viewcontroller.
Is there a way to use something like pointers from C++? When all changes in my array (at second view) change in the first view, that is, in fact I do not need to copy data because I use a pointer. If I can't use that how can I transfer my array after change back at first view?
Use Delegation to pass data back to previous class,
From First Class,
class FirstClass: UIViewController, SecondClassDelegate {
#IBAction func goToSecondClass(_ sender: Any) {
performSegue(withIdentifier: "SecondClassId", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? SecondClass {
destination.delegate = self
}
}
func finishPassing(stringPassed: String) {
print(stringPassed)
}
}
In Second Class,
protocol SecondClassDelegate {
func finishPassing(string: String)
}
class SecondClass: UIViewController {
#IBAction func btnPassDataPressed(_ sender: Any) {
var delegate: SecondClassDelegate?
delegate?.finishPassing(string: "Data passed from Second Class")
}
}
don't use pointer, transfer you array by NotificationCenter.
Three ways here:-
If you have to pass data to previous controller then use Custom Delegation.
If you have to pass data to next controller then, just assign data to next view controller variable.
You can get data by saving it in Userdafults.
I want to create a segue to pass data to another view controller but there are certain criteria that must happen for the segue to happen. If possible i would prefer to use the segue Id instead of the dragging method.
this is an example Im trying to accomplish
#IBAction func SubmitButtonPressed(sender: AnyObject) {
if 1<0 {
// dont perform segue
}else{
//Perform segue
// i want to pass this data in the next VC
var data = "foo"
//this is my segue id i want o use to go to the Second VC
var segueId = "segueForgotPasswordTwo"
// second VC
var secondVc = "viewController2"
// Iwant to to use prepare for segue but im getting errors in the parameters
prepareForSegue(UIStoryboardSegue, sender: AnyObject?){
}
}
}
Your question is a bit unclear but I believe this is what you are looking for...
func someFunction(){
if //some condition {
//code
}else if //some condition {
//code
} else {
//perform segue by using the folowing line. Assign the identifier to the segue in the storyboard.
//Do this by first creating a segue by dragging from a view controller to the destination view controller. Be sure to drag from the VIEWCONTROLLER, to the destination VIEWCONTROLLER. DO NOT just drag from the button. Next, choose the type of segue (eg. show or present modally), and then type in an indentifier for this segue.
performSegueWithIdentifier("SegueIdentifier", sender: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SegueIdentifier" {
//now find your view controller that you are seguing to.
let controller = segue.destinationViewController as! SomeViewController
//access the properties of your viewController and set them as desired. this is how you will pass data along
controller.property = someValue
}
}
Overview:
Hook the segue from the source view controller to the destination view controller (see left side red arrows)
Don’t hook it from the button to the destination view controller
Create an action for the button to do your custom condition check then perform segue
Screenshot:
Code:
var data = "foo"
#IBAction func buttonPressed(sender: UIButton) {
let someCondition = true
if someCondition {
performSegueWithIdentifier("showGreen", sender: self)
}
else {
performSegueWithIdentifier("showPink", sender: self)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showGreen" {
let greenVC = segue.destinationViewController as! GreenViewController
// Make sure the data variable exists in GreenViewController
greenVC.data = data
}
}
You can implement the shouldPerformSegueWithIdentifier function in your ViewController. When the segue is triggered, this function can cancel the segue if it returns false, so you can simply include whatever logic is required in this function and return true/false as appropriate.
I have a button with the following code:
#IBAction func buttonPress(sender: AnyObject) {
performSegueWithIdentifier("newAccount", sender: sender)
}
When the button is pressed it performs a segue. I want to pass a value to the new view controller so I added the following code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "newAccount" {
if let dvc = segue.destinationViewController as? NewAccountViewController {
dvc.testValue = "This is my test value I want to pass"
}
}
}
The NewAccountViewController doesn't receive the value (I don't get any error).
The code I have in my NewAccountViewController is:
var testValue:String?
When I print(testValue) I don't get anything.
Why isn't this working as expected?
You need to check if the class is set correctly
Like the ViewController in below image
There are maybe two reasons: 1. identifier is not set as "newAccount" in the storyboard; 2. you have put a navigator view controller into the NewAccountViewController, which would ask you to transfer the destination as UINavigationController instead of NewAccountViewController. Hope this helps.
Is there a way to do a validation before unwind a ViewController?
i have my ViewController1 and there is a unwind function
#IBAction func unwind(segue: UIStoryboardSegue) {
// make stuff with data
}
And a button from ViewController2 is conected with that unwind function, and i pass data from my ViewController2 to ViewController1 in override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
all works fine, but i want to do some validations.
if sender as? UIBarButtonItem == self.saveButton {
if let content = self.textFieldContent.text {
publish.content = content
publish.image = self.image
} else {
self.alertMessage("Content is empty")
}
}
The self.alertMessage() function appears but the ViewController2 is dismissed every time. And i dont want this to happens, how can i achieve that?
Use - (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender method instead if you need prevent unwinding on some conditions.