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.
Related
In a single button, i put both alart system and a pop up view. If the text fields are blank then it will send an alart. If everything is okay then it will show popup view. Alart system and pop up is conflicting. How do I set conditon to segue function when to perform or not?
The function is not written proper. I can understand. But I am confused writing it. How do i call the overrride func?
func stateCondition(state: Bool) {
if state {
print("Entered into the state") //entering into the func
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "info"{
_ = segue.destination as! InfoViewController
}
if segue.identifier == "popUp" {
let vc = segue.destination as! PopUpViewController
vc.age = Double(ageTextField.text!)!
vc.gender = genderTextField.text!
vc.bmi = Double(bmiLabel.text!)!
print("Entered into the segue") //is not entering into this func
}
}
}
}
Try to read the code and comments.
First of all, the method func prepare(for segue: UIStoryboardSegue, sender: Any?) must not be in another method. Somehow you managed to squeeze it in func stateCondition(state: Bool) . Second you are not calling performSegue(withIdentifier: identifier, sender: self) anywhere. You probably should :) Check out the code, hope it helps. I remember my first segue, it took me some time to understand what is going on.
class ViewController: UIViewController {
#IBOutlet private var ageTextField: UITextField!
#IBOutlet private var genderTextField: UITextField!
#IBOutlet private var bmiLabel: UILabel!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// 3
// This method gets called and there you do your stuff with respective VCs
if segue.identifier == "info", let infoViewController = segue.destination as? InfoViewController {
// 3.1
// If the identifer is set to INFO then you go to the InfoViewController and assigne message
infoViewController.message = "Some fields are empty"
} else if segue.identifier == "popUp", let popUpViewController = segue.destination as? PopUpViewController {
// 3.2
// If the identifer is set to POPUP then you go to PopUpViewController and assign age, gender and bmi
popUpViewController.age = "33"
popUpViewController.gender = "male"
popUpViewController.bmi = "20"
} else {
print("Identifer is none of the above")
}
}
#IBAction private func buttonTapped(_ sender: Any) {
// 1.
// First you need to figure out where you want to take the user
// You do that in the method getSegueIdentifier() where you get the identifier
let identifier = getSegueIdentifier()
// 2.
// Then you performSegue with that identifer
performSegue(withIdentifier: identifier, sender: self)
}
private func getSegueIdentifier() -> String {
if ageTextField.text?.isEmpty == true && genderTextField.text?.isEmpty == true && bmiLabel.text?.isEmpty == true {
return "info"
} else {
return "popUp"
}
}
}
class InfoViewController: UIViewController {
var message = ""
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
showAlert()
}
func showAlert() {
// show alert with message
print(message)
}
}
class PopUpViewController: UIViewController {
var age = ""
var gender = ""
var bmi = ""
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
showPopUp()
}
func showPopUp() {
// show popUp with age gender and bmi
print(age, gender, bmi)
}
}
There is general misunderstanding: You must not call prepare(for segue – besides the syntax is wrong anyway – the function is called by the framework just before the segue is performed.
You probably mean something like
func stateCondition(state: Bool) {
if state {
print("Entered into the state") //entering into the func
performSegue(withIdentifier: "info", sender: nil)
} else {
performSegue(withIdentifier: "popUp", sender: nil)
}
}
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "popUp" {
let vc = segue.destination as! PopUpViewController
vc.age = Double(ageTextField.text!)!
vc.gender = genderTextField.text!
vc.bmi = Double(bmiLabel.text!)!
print("Entered into the segue") //is not entering into this func
}
}
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
I'm trying to send data from popup view to DataView.
it actually works ! .However, when I go back to popup view to edit the text it doesn't show the text that was entered and sent to DataView.
I'm sending the data through protocol.
PopupView
protocol DataEnteredDelegate: class {
func userDidEnterInformation(data: String)}
#IBAction func DoneButton(_ sender: Any) {
if let data = openTextView.text {
delegate?.userDidEnterInformation(data: data)
self.dismiss(animated: true, completion: nil)
}
}
DataView
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "openSummary" {
let sendingVC: popupViewController = segue.destination as! popupViewController
sendingVC.delegate = self
}
}
// Protocol receving data from popup
func userDidEnterInformation(data: String) {
addJobSum.text = data
}
After the PopupViewController gets dismissed, it gets destroyed and no new instances are able to know what an old instance had as a text value for the Text View.
To fix it - create a string property inside PopupViewController and initialize the Text View's text property with its value inside some method, such as viewDidLoad():
class PopupViewController: UIViewController {
var textData: String?
/* more code */
func viewDidLoad() {
/* more code */
if let data = textData {
openTextView.text = data
}
}
}
Then, you'll have to inject the proper / needed text for textData inside prepare(for:) method (right before it's presented):
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "openSummary" {
let sendingVC = segue.destination as! PopupViewController
sendingVC.delegate = self
// This is the new line to be added:
sendingVC.textData = addJobSum.text
}
}
I am trying to go to two different VC with two different buttons. With the 'newGeneratedListBtn i only want to go to vc1. With the 'newEmptyList' button i want to go to vc3 with a bool value which works. But when i click first button 'newGeneratedListBtn' to go to vc1 I get error: "Could not cast value of type 'AppName.vc1' to 'AppName.vc3'.
Seems like when i click button to vc1 it tries to send the same values as i want to send to vc3. How can i solve this?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
let value = true
//Button to VC1
#IBAction func newGeneratedListBtn(_ sender: UIButton) {
performSegue(withIdentifier: "unwindSegueToVC1", sender: self)
}
//Value to send to VC2
override func prepare (for segue: UIStoryboardSegue, sender: Any!) {
let vc = segue.destination as! ListView
vc.newEmptyListValue = value
}
//Button to VC2
#IBAction func newEmptyList(_ sender: UIButton) {
performSegue(withIdentifier: "valueSender2", sender: self)
}
}
You need to cast for a specific identifier
override func prepare (for segue: UIStoryboardSegue, sender: Any!) {
super.prepare(for:segue,sender:sender)
if segue.identifier == "valueSender2" {
let vc = segue.destination as! ListView
vc.newEmptyListValue = value
}
else {
// it's unwindSegueToVC1
}
}
as both
performSegue(withIdentifier: "unwindSegueToVC1", sender: self)
performSegue(withIdentifier: "valueSender2", sender: self)
with call prepare
The problem is there is only one implementation of prepare(for:sender:), like this:
override func prepare (for segue: UIStoryboardSegue, sender: Any!) {
let vc = segue.destination as! ListView
vc.newEmptyListValue = value
}
Both of your segues pass through that one method. You must use a switch or other condition to figure out which segue this is, and send the info appropriate to that segue.
I need to get an index of one of UIView collections to know which is tapped then link to a corresponding array element in the next screen. Problem seems sender! that I have the error message:
Could not cast value of type 'UITapGestureRecognizer' (0x107dcdc20) to 'UIView' (0x107dc2578).
(I used UIView to create color tiles. Should I use label or buttons instead of UIView?)
import UIKit
class ColoringViewController: UIViewController {
var coloringItem: ColoringItem?
var colorListTileArray = [UIView]()
#IBOutlet var colorListTile: [UIView]! // UIView color tiles
override func viewDidLoad() {
super.viewDidLoad()
if coloringItem != nil {
for (var i = 0; i<colorListTile.count; i++) {
colorListTileArray += [colorListTile[i]]
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showColoringDescriptionSegue" {
let tappedTile = sender!.self //<- doesn't work
//let tappedTile = sender!.view as! UIView <- doesn't work either :(
let colorIndex = colorListTileArray.indexOf(tappedTile as! UIView)
print(colorIndex)
}
}
#IBAction func showColoringDescription(sender: AnyObject) {
performSegueWithIdentifier("showColoringDescriptionSegue", sender: sender)
}
}
You are close. The sender to showColoringDescription is the UITapGestureRecognizer. Change the signature to take one of those. Then pass sender.view to performSegueWithIdentifier.
In prepareForSegue, cast sender to UIView and use that for the lookup in the colorListTileArray:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showColoringDescriptionSegue" {
let tappedTile = sender as! UIView
let colorIndex = colorListTileArray.indexOf(tappedTile)
print(colorIndex)
}
}
#IBAction func showColoringDescription(sender: UITapGestureRecognizer) {
performSegueWithIdentifier("showColoringDescriptionSegue", sender: sender.view)
}
Since you're using a UITapGestureRecognizer to initiate the segue, the recognizer will be the sender in prepareForSegue You can get the associated view using the view property:
if let recognizer = sender as UITapGestureRecognizer {
let view = recognizer.view
...
}