Swift one out of three segue is not passing data - swift

I am trying to pass data to another controller with a segue after clicking on a button.
This is my code:
#IBAction func agilityDogBtnPressed(_ sender: Any) {
if let objs = controller.fetchedObjects, objs.count > 0 {
let course = objs[0]
self.performSegue(withIdentifier: "DogAgilitySegue", sender: course)
}
}
#IBAction func baseEducationBtnPressed(_ sender: Any) {
if let objs = controller.fetchedObjects, objs.count > 0 {
let course = objs[1]
self.performSegue(withIdentifier: "BaseEducationSegue", sender: course)
}
}
#IBAction func puppyBtnPressed(_ sender: Any) {
if let objs = controller.fetchedObjects, objs.count > 0 {
let course = objs[2]
self.performSegue(withIdentifier: "PuppyClassSegue", sender: course)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "DogAgilitySegue" {
if let destination = segue.destination as? ClassDetailsVC {
if let course = sender as? Course {
destination.course = course
}
}
} else if segue.identifier == "PuppyClassSegue" {
if let destination = segue.destination as? ClassDetailsVC {
if let course = sender as? Course {
destination.course = course
}
}
} else if segue.identifier == "BaseEducationSegue" {
if let destination = segue.destination as? ClassDetailsVC {
if let course = sender as? Course {
destination.course = course
}
}
}
My problem is that the first two segues are working perfectly fine.
The third one (PuppyClassSegue) is not passing the data through.
It opens the page but the data are not showing, basically the destination.course is not happening.
Any idea how is that possible?
Thank you!

It appears that course is nil , also you can do this by hooking all buttons to the same action and setting tags for them 0,1,2 respectively
#IBAction func agilityDogBtnPressed(_ sender: UIButton) {
if let objs = controller.fetchedObjects, objs.count > 0 {
let course = objs[sender.tag]
self.performSegue(withIdentifier: "SegueFromCon", sender: course)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? ClassDetailsVC {
if let course = sender as? Course {
print("hit here ",course)
destination.course = course
}
}
}
make 1 segue named say SegueFromCon from the current vc to the detailsVC

Related

Extract a String Variable from a Void function

here is my problem :
I would like to recover the variable jan from the Launch App() function and insert it in the override above instead of "Hello there".
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
let destVC : troisViewController = segue.destination as! troisViewController
destVC.dataFromFirst = "Hello there"
}
func launchApp(decodedURL: String) -> Void {
if presentedViewController != nil{
return
}
let jan: String = "\(decodedURL)"
print(jan)
self.performSegue(withIdentifier: "troissegue", sender: self)
}
The problem is the decoded URL is a barcode obtained by using the camera of my phone, a solution of type : destVC.dataFromFirst = launchApp() does not work...
Does Anyone has a similar issue ?
Thank you in advance
A simple solution is to pass the string as sender parameter
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "troissegue" {
let destVC = segue.destination as! troisViewController
destVC.dataFromFirst = sender as! String
}
}
func launchApp(decodedURL: String) -> Void {
if presentedViewController != nil { return }
self.performSegue(withIdentifier: "troissegue", sender: decodedURL)
}

Use the tag of UIButton in the prepare segue

I have a button that after tapping, perform a segue, in this perform, I send the tag of UIButton, with the sender
#IBAction func nextBtn(_ sender: UIButton) {
performSegue(withIdentifier: "more", sender: sender.tag)
}
and in the prepare segue, I try to use this tags, but appearntly i am doing it wrong
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "more" {
if let navigationVC = segue.destination as? UINavigationController, let openPDF = navigationVC.topViewController as? Morepage {
let senderTag = (sender as? UIButton)?.tag
if senderTag == 1 {
print(123)
} else if senderTag == 2 {
print(123)
}
}
}
}
The senderTag is shown as none or nil. could you help me to use sender.tag properly in the prepare segue.
many thanks
You can check your button tag following way. sender: will be sender not sender.tag
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "more" {
if let navigationVC = segue.destination as? UINavigationController, let openPDF = navigationVC.topViewController as? Morepage {
if yourButton.tag == 1 {
print(123)
} else if yourButton.tag == 2 {
print(123)
}
}
}
}
OR
if sender.tag == 1 {
print("Button 1 is pressed")
}

Data from parse is not being passed through prepareForSegue

I want to get the objectId from parse and pass it through segue. But the objectId is passing over as an empty string:
class QueryViewController: UIViewController {
var objectIdFormParse = String()
#IBAction func makeQueryButtonTapped(_ sender: UIButton) {
makeSearchObject.saveInBackground { (success, error) in
if error == nil {
if let getObjectId = makeSearchObject.objectId {
self.objectIdFormParse = getObjectId
print("objectId in queryVC: \(self.objectIdForomParse)")
}
//Successfully saved
} else {
//Error, check error
}
}
performSegue(withIdentifier: resultsSegue, sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == resultsSegue
{
let destination = segue.destination as! ResultsViewController
destination.objectIdFromQueryVC = objectIdForomParse
}
}
}
The print statement prints the objectId correctly, but the segue passes empty.
You can pass the data through perform segue. just change perform segue line with following one:
performSegue(withIdentifier: resultsSegue, sender: objectIdForomParse)
And in your prepare for segue method add following lines:
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == resultsSegue
{
let destination = segue.destination as! ResultsViewController
let objectIDParse = sender as! String
destination.objectIdFromQueryVC = objectIDParse
}
}
}
Perform segue when your error is nil since you are setting objectIdForomParse
only when your error is nil.
Update :
#IBAction func makeQueryButtonTapped(_ sender: UIButton) {
makeSearchObject.saveInBackground { (success, error) in
if error == nil {
if let getObjectId = makeSearchObject.objectId {
self.objectIdFormParse = getObjectId
print("objectId in queryVC: \(self.objectIdForomParse)")
performSegue(withIdentifier: resultsSegue, sender: self)
}
//Successfully saved
} else {
//Error, check error
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == resultsSegue
{
let destination = segue.destination as! ResultsViewController
destination.objectIdFromQueryVC = objectIdForomParse
}
}
}

Add two guard let in a prepare for segue function

I'm trying to build my first app with three tableViews which are hierarchical. The middle VC has two guard let in one prepare for segue function.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let destination = segue.destination as? AddMemberViewController else {
return
}
destination.club = club
guard let Destination = segue.destination as? TransactionViewController, let selectedRow = self.tableViewMember.indexPathForSelectedRow?.row else {
return
}
Destination.member = members[selectedRow]
}
That's how it looks like. Can I fix this, that both func get used by my app, because it just uses the one on the top.
The problem is if you want to segue to TransactionViewController the function already returns because segue.destination is not AddMemberViewController.
Instead you should give your segues different identifiers and ask for them in prepareForSegue. Something like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "AddMemberVCSegue" {
guard let destination = segue.destination as? AddMemberViewController else {
return
}
destination.club = club
}
if segue.identifier == "TransactionVCSegue" {
guard let Destination = segue.destination as? TransactionViewController, let selectedRow = self.tableViewMember.indexPathForSelectedRow?.row else {
return
}
Destination.member = members[selectedRow]
}
}
Just replace guards with if lets:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? AddMemberViewController {
destination.club = club
} else if let destination = segue.destination as? TransactionViewController, let selectedRow = self.tableViewMember.indexPathForSelectedRow?.row {
destination.member = members[selectedRow]
}
}
prepare(for is called for one specific segue, so executing both guard let after another is unnecessarily expensive.
Usually you are checking the identifier of the segue with a switch statement, replace the literal identifiers with your real values
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.identifier {
case "memberSegue":
let destination = segue.destination as! AddMemberViewController
destination.club = club
case "transactionSegue":
guard let selectedRow = self.tableViewMember.indexPathForSelectedRow?.row else { return }
let destination = segue.destination as! TransactionViewController
destination.member = members[selectedRow]
default: break
}
}

How to send multiple variables in one single sender?

I'm trying to send multiple variables in one single sender to show it in the Viewcontroller that it's connected to a segue named menuENG. I have five buttons and each button should send different information because is a dictionary and each button is a word. But I want to do this thru one sender. I tried the following code to make it but it is not working.
p.s.: I tried making an array but Xcode goes crazy.
#IBAction func abstractionENG(sender:UIButton) {
return perfomanceWithIdentifier("menuENG",sender:nil)
}
I think you can send the dictionary and there is something wrong with this line return perfomanceWithIdentifier("menuENG",sender:nil)
Anyway you can seperatly identify which button is clicked by tag and create dictionary on base of clicked button now you can send the complete dictionary to the sender.
#IBAction func abstractionENG(sender:UIButton) {
var dictSendData:[String:Any] = [:]
if sender == btn1
{
dictSendData.updateValue("abc", forKey: "key1")
dictSendData.updateValue("pqr", forKey: "key2")
}
else if sender == btn2
{
dictSendData.updateValue("xyz", forKey: "key1")
dictSendData.updateValue("123", forKey: "key2")
}
else
{
dictSendData.updateValue("123", forKey: "key1")
dictSendData.updateValue("abc", forKey: "key2")
}
self.performSegue(withIdentifier:"menuENG", sender: dictSendData)
}
1- assign segue action to IBAction function - assign tag id to ever button
you have already implemented it .
2- your IBAction function should run another function to run performSegue function
example :
self.performSegue(withIdentifier: "openAnotherViewController",sender: sender)
3- go to destination view Controller and create reciver variables "Maybe you can use optionals " .
var receiverInt :Int = 0
var receiverInt2 :Int = 0
3- go to the source view Controller and pass variables
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected variable/object to the new view controller .
if segue.identifier == "openAnotherViewController" {
let destinationController = segue.destination as! OtherViewControllerClass Name
// identify button by tag number
if (sender as! UIButton).tag == 200 {
destinationController.receiverInt = self.sourceInt
}else{
destinationController.receiverInt2 = self.sourceInt2}
}
}
Thank you everyone for the help fixed the issue by this way >
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
/* The following functions containts a group of conditionals which will change the scene depending of the IBAction selected */
#IBAction func abstractionENG(sender: UIButton) {
let data = [DiccioModel.abstraction().nameEng,DiccioModel.abstraction().descriptionEng,DiccioModel.abstraction().linkEng]
performSegueWithIdentifier("menuENG", sender: data)
}
#IBAction func webBrowserENG(sender: UIButton) {
let data = [DiccioModel.webBrowser().nameEng,DiccioModel.webBrowser().descriptionEng,DiccioModel.webBrowser().linkEng]
performSegueWithIdentifier("menuENG", sender: data)
}
#IBAction func latencyENG(sender: UIButton) {
let data = [DiccioModel.latency().nameEng,DiccioModel.latency().descriptionEng,DiccioModel.latency().linkEng]
performSegueWithIdentifier("menuENG", sender: data)
}
#IBAction func conditionalENG(sender: UIButton) {
let data = [DiccioModel.conditional().nameEng,DiccioModel.conditional().descriptionEng,DiccioModel.conditional().linkEng]
performSegueWithIdentifier("menuENG", sender: data)
}
#IBAction func operatingSystemENG(sender: UIButton) {
let data = [DiccioModel.os().nameEng,DiccioModel.os().descriptionEng,DiccioModel.os().linkEng]
performSegueWithIdentifier("menuENG", sender: data)
}
#IBAction func abstractionESP(sender: UIButton) {
let data = [DiccioModel.abstraction().nameEsp,DiccioModel.abstraction().descriptionEsp,DiccioModel.abstraction().linkEsp]
performSegueWithIdentifier("menuESP", sender: data)
}
#IBAction func webBrowserESP(sender: UIButton) {
let data = [DiccioModel.webBrowser().nameEsp,DiccioModel.webBrowser().descriptionEsp,DiccioModel.webBrowser().linkEsp]
performSegueWithIdentifier("menuESP", sender: data)
}
#IBAction func latencyESP(sender: UIButton) {
let data = [DiccioModel.latency().nameEsp,DiccioModel.latency().descriptionEsp,DiccioModel.latency().linkEsp]
performSegueWithIdentifier("menuESP", sender: data)
}
#IBAction func conditionalESP(sender: UIButton) {
let data = [DiccioModel.conditional().nameEsp,DiccioModel.conditional().descriptionEsp,DiccioModel.conditional().linkEsp]
performSegueWithIdentifier("menuESP", sender: data)
}
#IBAction func operatingSystemESP(sender: UIButton) {
let data = [DiccioModel.os().nameEsp,DiccioModel.os().descriptionEsp,DiccioModel.os().linkEsp]
performSegueWithIdentifier("menuESP", sender: data)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "menuENG") || (segue.identifier == "menuESP"){
if let destinationViewController = segue.destinationViewController as? DefinitionViewController{
if let data = sender as? Array<String>{
destinationViewController.tittle = data[0]
destinationViewController.def = data[1]
destinationViewController.link = data[2]
}
}
}
}
PS: note this code is connected to the DefinitionViewController ( Controller of the view) and to a model. ( project was made by M.V.C way).
Again Thx everyone for your help. hope the code help other people in the future.