Data between view controllers not passing - iphone

I am creating an application in which there are 6 view controller in storyboard. The thing is that data is shared between the default view controller and the first one ( say A and B) which i added. i am using the prepareforseque method for passing data. the problem started when i added two more view controller. lets say C and D i created two new swift files and changed the two view controller class name. i created a textbox and button in C and label in D. when i pressed the button, the value of the text field is not passing into the D view controller although i used the same methods and code which i used for A and B. do i have to do anything else when i want to pass data between two newly added view controller.
first viewcontroller in which when a button is pressed value 1 needed to be passed:
class PlaySelectMenu: UIViewController {
var value = Int()
#IBAction func twotofive(sender: AnyObject) {
value = 1
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let nextView : PlayGameView = segue.destinationViewController as! PlayGameView
nextView.x = value
}
}
the second view controller which receive the value and print it
import Foundation
import UIKit
class PlayGameView: UIViewController{
var x = Int()
override func viewDidLoad() {
super.viewDidLoad()
print(x)
}
}
here i have added both the view controller from the object library and not working with the default one which is present in storyboard by default. i dont know why these two viewcontroller are not working. please help.
Regards Dev

One solution would be to write the data out to NSUserDefaults and then read it back from NSUserDefaults in the other view controller. Probably not the proper or correct way to share data between two view controllers, but it's been a reliable work around for me.
Other than that, you'd need to share your code so that we can see what's occurring.

Can you post also the code in your controllers C & D. And also if you have copy/paste the code inside your first two controllers into the two others, are you sure that in your prepareForSegue method you have changed the name of the destination segue ?

Assuming you have created the segue in Storyboard:
All you need is to do is put all of needed updates in prepareForSegue because twotofive is called after prepareForSegue.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
value = 1
let nextView : PlayGameView = segue.destinationViewController as! PlayGameView
nextView.x = value
}

Since you have connected your segue from button click to view controller, when you press button segue is automatically called. Instead of connecting segue from button to VC, connect VC to VC. Then in button click method at the last add below line:
#IBAction func twotofive(sender: AnyObject) {
value = 1
self.performSegueWithIdentifier("<Name of the segue identifier>", sender: self)
}
This will call your prepareForSegue. If you are calling more then one VC using segue from a VC then you can use segue.identifier to check which VC was called as below
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if segue.identifier == "CVC" {
}

Related

How To Pass Dictionary To Another Dictionary In A Different View Controller

I have two view controllers (autoClaimViewController and reviewAutoViewController). In autoClaimViewController, I have a dictionary (reviewTableViewData) that is made up of a struct called claimData (it contains two string variables and a UIImage variable). When the user hits the "Review" button, I want the reviewTableViewData dictionary to be passed to the second view controller so that it's data can be displayed on a table view in the second view controller (reviewAutoViewController). How do I pass this dictionary to the other view controller?
Please make your answers understandable for a beginner - I'm still learning. I'm moving between view controllers using storyboard segues.
Thanks.
Additional Question: Will the images that I stored in the variables be passed when the dictionary is passed? In other words, do images work like Integers and Strings, where they can be passed between variables without an issue?
My code:
struct claimData {
var images = UIImage()
var imageTitle = String()
var relatedUnrelated = String()
}
class autoClaimViewController: UIViewController {
var reviewTableViewData = [claimData]()
#IBAction func reviewButton(_ sender: Any) {
//PASSES THE INFORMATION TO THE REVIEW VIEW CONTROLLER
//FIX THIS... IT NEEDS TO SEND THE reviewTableViewData ARRAY.
//MAKE A DICTIONARY IN THE REVIEW CONTROLLER THAT RECEIVES THE DICTIONARY FROM THIS VIEW CONTROLLER.
let vc2 = reviewAutoViewController()
//Find out how to transfer a dictionary from one view controller to another
}
I think your best bet is to set up a segue in your storyboards which takes you from 1st view to the second view. Here is a guide.
https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/UsingSegues.html
In both views have a place to store the information you want to pass. So create a var in the secon view to hold reviewTableViewData from the first view.
Then in the 1st view you call
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.destination is reviewAutoViewController
{
let vc = segue.destination as? TertiaryViewController
vc?.reviewTableViewData = reviewTableViewData
}
}
This get the data ready to be sent.
Then you perform the segue and the data should be passed for you. Perfomr the seugue with this func triggered by the button or whatever you use to tranisiton between views.
func performSegue(withIdentifier identifier: String,
sender: Any?){
enter code here
}

Variable shared between view controllers of storyboard?

My app is split into 2 storyboards: a character selection one and a main application one. When the user selects a character the app segues's to the main application, and all the views of that storyboard should now relate to the character the user selected.
I'm trying to find out the best way to share a String that will have the selected character's information between all the main application storyboard's views. Right now I'm using UserDefaults to just set a global variable:
func loadMainApp(sender: UITapGestureRecognizer) {
let currentCharcter = allCharacters[(sender.view?.tag)!]
let defaults: UserDefaults = UserDefaults.standard
defaults.setValue(currentCharacter, forKey: "CurrentCharacter")
performSegue(withIdentifier: "MainAppSegue", sender: self)
}
From there all the view controllers in the Main App storyboard can fetch the string from UserDefaults.
Is this the best way of doing such a thing or is there a better way?
The better way is to pass the character to the viewController you are segueing to, and the easiest way to do that is with prepare(for segue. If you change your performSegue call to pass the sender on by saying performSegue(withIdentifier: "MainAppSegue", sender: sender) you will be able to access that in prepare(for like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//Safely check to make sure this is the correct segue by unwrapping the sender and checking the segue identifier
if let tapGesture = sender as? UITapGestureRecognizer, let tapGestureView = sender.view, let mainViewController = segue.destination as? MainViewController, segue.identifier == "MainAppSegue" {
//Get a reference to the character that was selected
let currentCharacter = allCharacters[tapGestureView.tag]
//Pass the character to the new viewController
mainViewController.character = currentCharacter
}
}
I made a couple assumptions about the name of the viewController you are performing the segue to, and assumed it has a variable called character where you can send your character. Your new viewController now has a reference to the character.
If I understand you well. Personally I am using Singeltons for achieving Global variable between Views rather than UserDefaults
class SomeClass{
static let sharedInstance = SomeClass()
var someString = "This String is same from any class"
}
Usage inside of some function :
SomeClass.sharedInstance.someString = "Changing Global String"

Segue w/ Tab View Controller Keeps Passing Value

I am working on an iOS application that is built around a Tab View Controller. I have created a "Contacts" tab, where a user can find and select a contact from a list. When the user selects the contact, it takes the contact's name and passes it to a different tab. That function is being done like so:
func passName(name: String) {
let navTab = self.tabBarController!.viewControllers![2] as! UINavigationController
let homeTab = navTab.viewControllers[0] as! MainController
homeTab.passedName = name
tabBarController?.selectedIndex = 2
}
Everything works as it should so far (name is loaded into text field). My issue is that the value seems to keep coming back every time I change tabs and then go back to my Home tab. For example, if I select "John" from my contacts, it will take me to the Home Tab and put John's name in a textfield. Let's say I delete the last two letters of the name, so now it is "Jo". If I load a different tab and come back, the name field has been reset to "John". It's as if the value gets re-passed every time I open the Home Tab. Also, every time I load the Home Tab after passing a name, my console prints: "Name Passed: John", so it shows that this is being processed every single time the tab appears. Here is my code for processing the name:
var passedName: String!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
//Checks if name was passed to controller
if let validName = passedName {
print("Name passed: \(validName)")
nameTextField.text = validName
}
}
Am I passing the data incorrectly? I was thinking it might be because I have the above code being called in the viewWillAppear method, but that doesn't make sense, as essentially the data is only being passed one time from the Contacts tab. Thanks!
The problem is that you're not actually passing the value back to the original view. Apple's recommendation for passing information between classes is to use the delegate pattern. This allows the modal view to call the delegate class's function, which changes the name local to the original view because that function is declared in the original view's viewController. You can read more about the pattern in this tutorial, but I've also included a brief example relevant to your use case below.
mainViewController:
class namesTableViewController: UITableViewController, editNameDetailsViewControllerDelegate {
var name : String
#IBAction func editButtonPressed(_ sender: UIBarButtonItem) {
performSegue(withIdentifier: "editPerson", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "editPerson" { //Modal segue
let navController = segue.destination as! UINavigationController
let controller = navController.topViewController as! editNameViewController
controller.delegate = self
if let person = sender as? Person {
print("Sending person to edit")
controller.personToEdit = person
}
} else {
super.prepare(for: segue, sender: sender)
}
}
//Protocol function
func changeName(n: String, controller: UIViewController) {
name = n
dismiss(animated: true, completion: nil)
}
}
editNameViewController:
class editNameViewController: UIViewController {
#IBOutlet weak var personNameTextField: UITextField!
var personToEdit : Person?
weak var delegate : PersonTableViewController?
override func viewDidLoad() {
super.viewDidLoad()
if personToEdit != nil {
personNameTextField.text = personToEdit?.name
}
}
// Button Actions
#IBAction func saveButtonPressed(_ sender: UIBarButtonItem) {
delegate?.personDetailsView(n: personNameTextField.text, controller: self)
}
}
Finally, the protocol class :
protocol editNameDetailsViewControllerDelegate : class {
func personDetailsView(n: String, controller: UIViewController)
}
Hope this helps.
The problem is "passedName" variable doesn't changed its value every time you edit it in your UITextField. Keep in mind that every time you change tabs, the UIViewController will call viewWillAppear and viewDidAppear. So your UITextField will always show passedName value once you select other tab and return.
I suggest that every time you edit the textfield you should update passedName value.
Sorry for my bad english.

Swift segue performed multiple times

A segue in my app is being called multiple times, which is causing the view to continuously "load" until the app stops calling the segue function. It does this about 4 times until it's finished. After placing breakpoints in the code I noticed that the app is bouncing between these two functions:
if success {
self.performSegueWithIdentifier("startGame", sender: "user")
}
That is the action that triggers the segue (the user swipes something). It then goes to the next breakpoint:
if (segue.identifier == "startGame") {
let destinationNavigationController = segue.destinationViewController as! GameViewController
destinationNavigationController.user = self.users[self.currentUser]
}
The app goes back and forth between the two sections about 4 times. When I created the segue in my storyboard I made sure to wire the segue from the view controller itself (not a table/UI view) to the destination view.
What else can I do to fix this?
Thanks!
In storyboard, create a segue by holding control and dragging from the yellow icon of the 1st view controller to the 2nd view controller.
Give it an id, and the kind should be push if they are embedded in a navigation controller.
In your 1st view controller class:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "startGame" {
let viewController = segue.destinationViewController as! GameViewController
// this next view controller should have property that will store passed value
viewController.user = self.users[self.currentUser]
}
}
When you want to move to the next view controller:
performSegueWithIdentifier("startGame", sender: self)

How can I use the selected data from a UIDatePicker in another view in IOS8?

I'm very new to IOS 8 and programming in general. I would like to populate a UIButton's label text with the value from a UIDatePicker. When the user presses the button, a popover appears with a date picker. I have created a new view controller imbedded in a navigation controller for my date picker. They are connected using a popover segue. My question is once the user selects a date, how can I transmit this information back to the original view controller to show the value on the button label. Any help would be greatly appreciated.
To pass a value between 2 viewcontrollers using segues is easies done like this:
class VC1:UIViewController {
#IBAction func next() {
let valueToPass = NSDate() // Could be anything that conforms to AnyObject
self.performSegueWithIdentifier("segueID", sender: valueToPass) // Use this method unless you're connecting a button to a viewcontroller in storyboard
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let vc2 = segue.destinationViewController as VC2 // The viewcontroller you're going to
vc2.date = sender as NSDate // If you connected button to vc in storyboard sender will be nil, so in that case just set the vc2.date directly here
}
}
class VC2:UIViewController {
var date:NSDate! // Property you want to pass to
}