segue getting twise call in swift - ios

I have two view Controller one is ScheduleController and other is EditShiftController. In ScheduleController I have a table view name is scheduleTable. In the scheduleTable I have a cell with identifier ScheduleWithData. In this cell i have two different button Button EDIT and Button DELETE. i have directly connected button EDIT with EditShiftController with segue identifier editShiftSegue.
The Code of TableViewCell.swift
var editShiftClick: (() -> Void)? = nil
#IBAction func editShiftBtn(sender: AnyObject) {
if let onButtonTapped = self.editShiftClick {
onButtonTapped()
}
}
The Code of ScheduleController.swift
myCell!.editShiftClick = {
self.performSegueWithIdentifier("editShiftSegue", sender: dataTemp[indexPath.row].id)
}
The function for prepareSegue in ScheduleController.swift
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "editShiftSegue") {
print("senderIndexPath=\(sender)")
if (sender != nil) {
let svc = segue.destinationViewController as! EditShiftViewController;
svc.label = String(sender)
}
}
}
Snip Shot of Segue
enter image description here
When I click on EDIT button then EditShiftController getting twice call I don't know why
please, can any one help me here Thank you in Advance

myCell!.editShiftClick = {
//self.performSegueWithIdentifier("editShiftSegue", sender: dataTemp[indexPath.row].id)
}
Comment self.performSegueWithIdentifier("editShiftSegue", sender: dataTemp[indexPath.row].id) this line because if you have connected edit button directly with segue then no need to performsegue programatically also!!
Update:
myCell!.editShiftClick = {
self.performSegueWithIdentifier("editShiftSegue", sender: self)
}
don't comment that line and delete that segue which is given from edit button. give segue from viewcontroller to viewcontroller and give identifier editShiftSegue and then perform segue as above code.

Related

Data turns Nil when passing from previous View Controller going to another View Controller using Segue

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.

Incorrect data passed on first click of button

Salutations,
My problem is as follows, I have an app I am working on which contains two views. The first simply has 2 buttons labeled "Slide Show One", and "Slide Show Two".
When I click on the first button, it displays the information for the second slideshow as (due to my supreme novice-ness), I select which of the slideshows to select via a boolean as follows:
var button : Bool = false;
then:
#IBAction func slideShowOne() {
button = true;
}
#IBAction func slideShowTwo() {
print("clicked button 2");
button = false;
}
Finally in the prepareForSegue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let passedPic = segue.destination as! ViewControllerTwo;
if(button == true) {
print(button);
passedPic.picsChosen = sLS1;
}
if(button == false) {
print(button);
passedPic.picsChosen = sLS2;
}
}
Only way to have it display the correct information is by clicking on say button 1 for btn1 slideshow, going back, then clicking on button 1 again. Why is this, does it have anything to do with how swift handles function calls?
Aside: Swift knowledge is now a grand total of one week.
EDIT: Got it working, much appreciated. Now a quick question, at this time my two IBActions are empty, but required since they have segues attached to them, would be the best way to either make them meaningful, or perhaps still be able to segue; I assume the prepare function is an absolute must, otherwise there is no way (of which I know), to send the required data to my second VC.
#IBAction func slideShowOne() {
//self.performSegue(withIdentifier: "slideOne", sender: self);
}
#IBAction func slideShowTwo() {
//self.performSegue(withIdentifier: "slideTwo", sender: self);
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
let passedPic = segue.destination as! ViewControllerTwo;
if(segue.identifier == "slideOne") {
passedPic.picsChosen = sLS1;
} else {
passedPic.picsChosen = sLS2;
}
}
Try connecting view controller to view controller via storyboard - same ctrl dragging but whole view controller to other.
Give that segue identifier -> select identifier and on forth tab give it identfiier.
After that in one of your buttons, eg:
#IBAction func slideShowOne() {
button = true;
self.performSegue(withIdentifier: "toTheOtherVC", sender: self)
}
And you will have desired behaviour.
The reason is that: override func prepare(for segue: UIStoryboardSegue, sender: Any?) always be executed firstly.
So the actual workflow is as following:
-> 1) Initialize first view
-> 2) var button = false
-> 3) the user taps btn1
-> 4) func prepare is called
-> 5) second view is displayed (var button is still false at this moment, that's why you get incorrect response)
-> 6) func slideShowOne() is called (the user already is in second view)
-> 7) var button = true caused by func slideShowOne() (the user already is in second view)
-> 8) the user goes back
-> 9) the user taps btn1 again
-> 10) func prepare is called
-> 11) second view is displayed (the user gets correct response because value of var button has been changed in step7)
Let me know if you have any other questions. Have fun. : )

How can i create a segue that pass data to another view controller only if certain criteria are met

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.

iOS Segue not working as expected when passing value

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.

Navigation Between Two View Controller

I have two View Controllers. in mainViewController there is TabBarButton when it clicked user goes to 1stViewController and there is UIButton when it has clicked user goes to 2ndViewController.
before making my 2ndViewController everything worked fine. but after i add segue function in my program i got error.
could not cast value of type 'Calculator.1stViewController' (0x791a8) to 'Calculator.2ndViewController' (0x794c8).
briefly my code is
#IBAction func CalculateGpa(){
//Calucation Goes Here
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var AnotherName : 2ndViewController = segue.destinationViewController as! 2ndViewController
//Code here
}
UIButton Perform the segue and BarButton do nothing it just go to 1stView Controller. when i run the program and click BarButton im getting that above error.
its because prepareForSegue cant identify to which button it should perform right? how to solve it?
try this code.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "youridentifiername") {
//your class name
if let viewController: DealLandingViewController = segue.destinationViewController as? DealLandingViewController {
viewController.dealEntry = deal
}
}
}

Resources