Unable to send an int value between view controller and table view controller in swift - swift

the class PreferencesViewController sends nil through prepare for segue regardless if IBActions are taken or not. It seems that something is wrong in my prepare for segue but I'm not sure. I'm not trying to assign to any label or anything I'm just trying to send the int value to another variable in the class Pick2_1. Thanks in adavance
import UIKit
class PreferencesViewController: UIViewController {
var preference = 0
#IBAction func nImportant(sender: UIButton) {
preference = -1
print(preference)
}
#IBAction func N(sender: UIButton) {
preference = 0
print(preference)
}
#IBAction func mImportant(sender: UIButton) {
preference = 1
print(preference)
}
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.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "preferenceSegue" {
let preferenceVC = segue.destinationViewController as! Pick2_1
preferenceVC.preferenceSent = preference
print(preference)
}
}
}

Ok segue is directly connected to the button. You have to set the segue between your 2 controllers set the identifier and in the #IBAction you should call performSegueWithIdentifier func

Related

Change variable while dismissing modal controller

EDIT: I have decided to change the way my app works, so this problem is solved. Thanks to everyone who helped!
I have a modal controller where when I press a button it dismisses the view. What I want to do is change a variable in another view controller when I dismiss it, is that possible? Or, if this doesn't work, is there a way for me to access the changed variable of another swift file? I will add my code below:
class PopupViewController: UIViewController {
var event = ""
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func dismiss(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
#IBAction func event910(_ sender: Any) {
event = "storyTime"
dismiss(animated: true, completion: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! ViewController
vc.event = event
}
}
I want to pass the changed variable "event" to another view controller, how can I do this?
Delegate View Controller is as follows. : -
it is the place where you will send the data to the next swift file
protocol myprotocol {
func anyfunction(_ param1:String)
}
struct mystruct1 {
var delegate:myprotocol?
// where you want tot start the delegate / send the data to the next file
func anymethod(){
delegate.anyfunction(sendTheDataYouWant)
}
}
// it is here you will receive the data
class anyclass:UIViewController ,myprotocol {
let class1 = mystruct1()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
class1.delegate = self
}
func anyfunction(param1:String){
// here Save the data you want
// because this function will be triggered as delegate will be called
}
}
ps:- I reccomend you to read https://docs.swift.org/swift-book/LanguageGuide/Protocols.html
& apple docs

Swiching between 2 diferent NSViewControllers with data

I'm absolute newbie in Swift and OSX development, and I'm sorry if my question will be too noob. I want to understand principles of navigation between NSViewControllers.
I have my default ViewController, where are login and password fields and button to login. After click on button, returns token. And now I trying to change "view" to SecondViewController and save somewhere token, I will need it in future. How can I do it? and it possible to do this in function?:
#IBAction func loginButton(_ sender: Any) {
....
}
Thank you!
You need to use segues to perform this action.
First make the segues connections between the ViewControllers using to storyboard editor. After that you need to give the segues an identifier on the storyboard's attributes inspector. Then in your code you can call the new ViewController by the segue like the code below.
With this code you can pass the data using the button:
class ViewController: NSViewController {
var dataToPass: String = "DataToPass"
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func loginButton(_ sender: Any) {
performSegue(withIdentifier: NSStoryboardSegue.Identifier(rawValue: "segueIdentifier"), sender: self)
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
if segue.identifier!.rawValue == "segueIdentifier" {
let destinationViewController = segue.destinationController as! ViewController2
destinationViewController.dataToReceive = dataToPass
}
}
}
class ViewController2: NSViewController {
var dataToReceive: String
override func viewDidLoad() {
super.viewDidLoad()
}
}
And with this code you will use the override viewWillAppear
class ViewController: NSViewController {
var dataToPass: String = "DataToPass"
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear() {
performSegue(withIdentifier: NSStoryboardSegue.Identifier(rawValue: "segueIdentifier"), sender: self)
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
if segue.identifier!.rawValue == "segueIdentifier" {
let destinationViewController = segue.destinationController as! ViewController2
destinationViewController.dataToReceive = dataToPass
}
}
}
class ViewController2: NSViewController {
var dataToReceive: String
override func viewDidLoad() {
super.viewDidLoad()
}
}
In both cases you need to assure the data you want to pass to the other view controller is not null.

Passing Data through multiple View Controllers with segue [Swift 3.0 Xcode]

NOTE: Question has been edited in an attempt to be more clear with my issue.
Hey, I am trying to pass data through multiple VCS. I want to pass data (arrays) from V2 -> V3 and then V3 -> V1 but I want to be able to only navigate through the VCs as such: V1 - V2 - V3 and V3 - V2 - V1.
So what I need to learn is how to pass data without navigating to a different VC as well as setting up two preparetosegue methods to pass data between V2 -> V3 and V3 -> V1 while also being able to navigate between all VCs. When I create my first preparetosegue, I am unable to use other segues associated in my VC to navigate to other VCs without getting a Fatal Error.
Can anyone help me?
Any input would be greatly appreciated!
Heres my attempt:
import UIKit
class ViewController: UIViewController {
var name = String()
var StopButInfo = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
import UIKit
class SecondViewController: UIViewController {
var StringArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBOutlet var PHeight: UITextField!
#IBOutlet var PName: UITextField!
#IBAction func Search(_ sender: Any) {
if PHeight.text != ""{
performSegue(withIdentifier: "SearchSegue", sender: self)}
let CDstart = String(describing: Date())
StringArray.append(CDstart)
StringArray.append(PName.text!)
StringArray.append(PHeight.text!)
}
override func prepare(for SearchSegue: UIStoryboardSegue, sender: Any?){
let thirdController = SearchSegue.destination as! ThirdViewController
thirdController.SearchButInfo = StringArray
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
import UIKit
class ThirdViewController: UIViewController {
var height = String()
var SearchButInfo = [String]()
var StringArray = [String]()
#IBAction func Stop(_ sender: Any) {
if StringArray.count != 0{
performSegue(withIdentifier: "SegueToStart", sender: self)
}
let CDStop = String(describing: Date())
StringArray.append(CDStop)
StringArray.append(height)
}
override func prepare(for SegueToStart: UIStoryboardSegue, sender: Any?){
let firstController = SegueToStart.destination as! ViewController
firstController.StopButInfo = StringArray}
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.
}
}
You need to check which view controller's segue is about to be performed, this can be done like this inside prepare(for segueMVH: UIStoryboardSegue, sender: Any?) method:
if let firstController = segueMVH.destination as! FirstViewController {
// Set first view controller's data
} else if let secondController = segueMVH.destination as! SecondViewController {
// Set second view controller's data
} else if let thirdController = segueMVH.destination as! ThirdViewController {
// Set third view controller's data
}
Note: It's better to use a different identifier for each segue to be able to distinguish between them.
The error you got on let secondController = segueMVH.destination as! ThirdViewController is saying that you are casing HC.ViewController into ThirdViewController and that's why it failed. It means that the destination view controller of your segue is not ThirdViewController.
To further help you understand segue: A segue is a connection between a source view controller and a destination view controller and can be only used between them two. See this picture:
In this case, I have a segue connection in my storyboard connected between my VC1's button and VC2. In this case, my button click will trigger this segue and prepare(for segue) method can only be in VC1 where it passes data to VC2.
So in your situation, you believe that the destination of your segue is ThirdViewController but it's actually not. So please check your segue with identifier segueMVH to see if it is connected between your current view controller and your ThirdViewController.
Hope this helps

Delegate using Container View in Swift

I'm developing an app for iPad Pro. In this app, containerView use to add additional views and interact with them.
First, I created a protocol:
protocol DataViewDelegate {
func setTouch(touch: Bool)
}
Then, I created my first view controller
import UIKit
class ViewController: UIViewController, DataViewDelegate {
#IBOutlet var container: UIView!
#IBOutlet var labelText: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
func setTouch(touch: Bool) {
if touch == true {
labelText.text = "Touch!"
}
}
}
And finally, I created a view that will be embedded in containerView.
import UIKit
class ContainerViewController: UIViewController {
var dataViewDelegate: DataViewDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func touchMe(sender: AnyObject) {
dataViewDelegate?. setTouch(true)
}
}
But for some reason, nothing happened, the first view controller receives nothing in setTouch function.
My question is: In this case, using container, how can I make the communication between two ViewsControllers?
Like #nwales said you haven't yet set the delegate. You should do set the delegate in prepareForSegue function on your first viewController (who contain the viewContainer)
First select the embed segue and set an identifier in the attributes inspector.
Then in the parentViewController implement the func prepareForSegue like this:
Swift 4+:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "the identifier") {
let embedVC = segue.destination as! ViewController
embedVC.delegate = self
}
}
Below:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if (segue.identifier == "the identifier") {
let embedVC = segue.destinationViewController as! ContainerViewController
embedVC.dataViewDelegate = self
}
}
Looks like you defined the delegate, but have not set the delegate. This happens to me all the time.

Swift - passing text and int from vc1 to vc 2 (uitextfield -> label in vc2)

Passing only input text from textfield to label in second VC works!! But i want when user type number 10 in uitextfield, ( 1 ticket is 2 euros so 10 tickets * 2 euro is 20) and when i click PAY button, so that SUM can be displayed in label in second VC, i think that viewdidload in VC2 is happening before prepareForSegue, i don't know. It works when i click second time on PAY button, but not when i first click PAY button where label displays zero, help :) Embedded in navigation controller for navigation.
VC1
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var howManyTickets: UITextField!
var sumTicketsAndPriceOfTickets = Int()
var priceOfTicket = 2 // euros
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func platiTeKarte(sender: AnyObject) {
sumTicketsAndPriceOfTickets = howManyTickets.text.toInt()! * priceOfTicket
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let driver = segue.destinationViewController as! primaocViewController
var whatToPass = sumTicketsAndPriceOfTickets
driver.receiver = whatToPass
}
}
VC2
import UIKit
class primaocViewController: UIViewController {
#IBOutlet weak var displaySum: UILabel!
var receiver:Int!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.displaySum.text = String(receiver)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
If your button is wired directly to a segue, then you don't need an #IBAction as well. As you are seeing, the prepareForSegue is happening before the #IBAction for your Pay button. Just compute your value in prepareForSegue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let driver = segue.destinationViewController as! primaocViewController
driver.receiver = (howManyTickets.text.toInt() ?? 0) * priceOfTicket
}
I changed the calculation of the pay to use the nil coalescing operator ??. This is generally a safer approach because if the toInt() returns nil for any reason, it will in this case just use 0 instead of crashing.