Can't get the value of a var in another class - ios

I'm trying to get the value of a String var from an another class, but when i'm using it on the new class, the value is empty.
I've got the MainViewController.swift class with :
var movieIDSelected = String()
#IBAction func tapPosterButton(_ sender: UIButton) {
switch sender.tag
{
case 101: movieIDSelected = theaterMovieID[0]
print(movieIDSelected) //The value isn't empty
break
}
}
And the second MovieViewController.swift class with :
var HomeView = ViewPop()
override func viewDidLoad() {
super.viewDidLoad()
let movieID = HomeView.movieIDSelected
print(movieID) //The value is empty
}

With your current code try this in MainVC
if let home = UIApplication.shared.keyWindow?.rootViewController as? ViewPop {
print("home exists ",home.movieIDSelected)
}
//
but you should have only 1 segue to the destinationVC and link it to the VC not a segue for every button , then implement prepareForSegue and fire performSegue inside the button action to make the segue
//
#IBAction func tapPosterButton(_ sender: UIButton) {
switch sender.tag
{
case 101: movieIDSelected = theaterMovieID[0]
print(movieIDSelected) //The value isn't empty
self.performSegue(withIdentifier: "goToNext", sender:1)
break
}
}
//
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let des = segue.destination as! MovieViewController
des.sendedValue = self.movieIDSelected
des.buttonNumber = sender as! Int
}
//
class MovieViewController : UIViewController {
var sendedValue = ""
var buttonNumber = 0 // default value won't affect
}

Related

Can not pass Data To ContainerView

I have tried 2 methods to pass the data from ViewController to ContainerView, with and without segue
Here is without segue method
ViewController
class DetailPostBookReviewVC: UIViewController {
var postid: String!
#IBAction func Menubutton(_ sender: Any) {
print(postid!)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "MenuBookReviewVC") as! MenuBookReviewVC
vc.favpostid = postid
}
ContainerView
class MenuBookReviewVC: UIViewController {
var favpostid = String()
#IBAction func Deletepost(_ sender: Any) {
print(favpostid)
}
}
result: favposid has Nill Value
UPDATE this is with segue method
class DetailPostBookReviewVC: UIViewController {
var postid: String!
#IBAction func Menubutton(_ sender: Any) {
print(postid!)
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
if (segue.identifier == "toMenuBookReviewVC") { //"toMenuBookReviewVC" is identifier
let vc = segue.destination as! MenuBookReviewVC
vc.favpostid = postid!
}
}
Pass your data like. User prepare(for:sender:)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if
segue.identifier == "MyIdentifierInStorybiard", // Set that
let controller = segue.destination as? MenuBookReviewVC {
controller.favpostid = postid
}
}
I think you postid is not String type so print the null value
In this way, you can't pass data for the container view. if in this way without presenting controller and push controller you can use the global variable then direct pass data and use any controller you want to use.
Example
import UIKit
class ViewController: UIViewController {
var postid: String!
override func viewDidLoad() {
super.viewDidLoad()
postid = "23" // You change your post ID
}
#IBAction func Menubutton(_ sender: Any) {
favpostid = postid
}
}
var favpostid : String!
class MenuBookReviewVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print(favpostid)
}
}
For Passing Data To Container View you can use this
UserDefaults.standard.set(value, forKey: "SomeKey")
after your data is used you can clear that default value.
UserDefaults.standard.set("", forKey: "SomeKey")

swift - return and pass multiple arrays and an Int via Segue

I'm nearly there with a small basic program I'm writing (still learning) and I've hit a roadblock.
I can now pass 1 array between 2 view controllers and successfully print it when I hit a button in the 2nd one.
However, what I really want to do is pass 2 arrays and an Integer, created from a function on the first VC and have them accessible via the 2nd VC.
Code for 1st VC is here :
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToWorkout" {
if let destVC = segue.destination as? WorkoutViewController {
destVC.bothArrays = self.testFunction()
}
}
//Get the new view controller using segue.destinationViewController.
//Pass the selected object to the new view controller.
}
func testFunction() -> [String] {
let randomArray1 = ["blah","blah","ploop"]
let randomArray2 = ["alan", "john"]
let randomInt = 5
return BOTH ARRAYS AND INT TO SEND TO THE NEXT VIEW CONTROLLER?
}
#IBAction func goPressed(_ sender: UIButton) {
performSegue(withIdentifier: "goToNextVC", sender: self)
}
and 2nd VC here :
class WorkoutViewController: UIViewController {
var randomArray1 = [String]()
var randomArray2 = [String]()
var randomInt = 0
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func nowButtonPressed(_ sender: UIButton) {
print(randomArray1)
print(randomArray2)
print(randomInt)
}
}
I can get it working with just one array but I need more than one array and a value to be passed! I've tried playing around with it (e.g. trying '-> [String], [String], Int) but no luck
Any help much appreciated!
You can simply use a tuple to include several variables of different types in a single variable. You should pass the tuple including all 3 variables in your performSegue function as the sender argument, then assign them to the relevant instance properties in the prepare(for:) method.
If you want to keep the function for generating the variables, you should change the return type of the function to a tuple that can fit the 3 variables.
func testFunction() -> (arr1:[String],arr2:[String],randInt:Int) {
let randomArray1 = ["blah","blah","ploop"]
let randomArray2 = ["alan", "john"]
let randomInt = 5
return (randomArray1, randomArray2, randomInt)
}
Then assign the return value of testFunction to the sender input argument of performSegue:
performSegue(withIdentifier: "goToNextVC", sender: testFunction())
Assign the variables:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToWorkout" {
if let destVC = segue.destination as? WorkoutViewController, let variablesToBePassed = sender as? (arr1:[String],arr2:[String],randInt:Int) {
destVC.randomArray1 = variablesToBePassed.arr1
destVC.randomArray2 = variablesToBePassed.arr2
destVC.randomInt = variablesToBePassed.randInt
}
}
}
As others have suggested, you can refactor your function to return a tuple, and then use that to pass to your other view controller:
//This is the tuple data type we use to pass 2 string arrays and an Int
typealias parameterTuple = ([String], [String], Int)
func testFunction() -> parameterTuple {
let randomArray1 = ["blah","blah","ploop"]
let randomArray2 = ["alan", "john"]
let randomInt = 5
return (randomArray1, randomArray2, randomInt)
}
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToWorkout" {
if let destVC = segue.destination as? WorkoutViewController {
//refactor WorkoutViewController to have a parameters property
//of type parameterTuple, split out the tuple and pass each part to
//a different property in your WorkoutViewController
destVC.parameters = testFunction()
}
}
}

assing object with prepareForSegue becomes nil in Swift 3

Sir,
I am trying to implement a form and pass the Data object below
import UIKit
import GRDB
class Staff: Record {
var id: Int64?
var compId: Int64 = 0
var chiName: String = ""
var engName: String = ""
to the table view controller loading the child record. when it comes to implementation, it seems getting null and does not make sense. Would you please tell me how to ensure the second view controller does not receive null objects under this case ?
Below is the
Log :
Here is my code:
First UIView Controller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("view salary X ")
print(dummy)
print(dummy.id ?? "0")
if let secondController = segue.destination as? ViewSalaryTableViewController {
secondController.dummyStaff = dummy
}
}
Second UITableView Controller :
public var dummyStaff : Staff?
override func viewDidLoad() {
super.viewDidLoad()
..
print("arrive dummyStaff")
print(dummyStaff ?? "njull")
}
Storyboard partial draft :
Storyboard setting
Make sure the type casting for secondController is working. If you have multiple segues, use segue identifier to distinguish. Below code worked fine for me:
class MyBook {
var name:String!
}
ViewController 1
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "Vc1ToVc2" {
let book = MyBook()
book.name = "Harry"
if let destinationVc = segue.destination as? ViewController2 {
destinationVc.book = book
}
}
}
ViewController 2
var book:MyBook?
override func viewDidLoad() {
super.viewDidLoad()
print(book?.name ?? "No name")
}
Prints: Harry

How to transfer data between view controller using segues

I'm trying to pass data using a prepare(for segue:) function but it's showing nil in the second VC. Am I doing anything wrong?
class ViewController: UIViewController {
var first : [String] = []
#IBOutlet weak var passField: UITextField!
#IBOutlet weak var userID: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func login(_ sender: Any) {
let user : String = self.userID.text!
let password : String = self.passField.text!
if user != "" && password != "" {
let postString = ["username":user, “password”: password]
var request = URLRequest(url:URL(string:"http://mydomainhere.com/api/login")!)
request.httpMethod = "POST"
request.httpBody = try! JSONSerialization.data(withJSONObject: postString, options:.prettyPrinted)
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil {
print("error=\(error)")
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] {
let firstName = json["first_name"] as? String
let lastName = json["last_name"] as? String
self.first.append(firstName!) //putting into Array
self.performSegue(withIdentifier: "loginSegue", sender: self)
}
} catch {
print(error)
}
}
}
}
// data transfer to another controller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "loginSegue" {
let secondController = segue.destination as? SecondVC
secondController?.name = first //passing to next VC //* here having the issue its not passing the data to next VC
print(first) // here first is printing perfectly
}
}
}
// second View Controller
class SecondVC: UIViewController {
var menu_vc : MenuViewController!
var name : [String]? // passing to this Array
override func viewDidLoad() {
super.viewDidLoad()
print(name) // here printing nil
}
}
As suggested by #Sweeper, it could very well be that your destination view controller is embedded in a UINavigationViewController, hence your segue.destination is in fact a UINavigationViewController, not a SecondVC.
You can try this code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var destinationViewController = segue.destination
if let navigationController = destinationViewController as? UINavigationController {
destinationViewController = navigationController.visibleViewController ?? destinationViewController
}
if let secondController = destinationViewController as? SecondVC {
secondController?.name = first
}
}
Of course the first four lines of code could be refactored in an appropriate function (even better if in an extension of UIViewController).
If that solves the problem, you can watch cs193p Stanford iOS course for further details.
In particular watch https://www.youtube.com/watch?v=HQrXM2zUPvY&index=6&list=PLPA-ayBrweUz32NSgNZdl0_QISw-f12Ai starting from the 30:20 mark.
Everything seems perfect with the below snippet
var first : [String] = []
#IBAction func btnTapped(_ sender: Any) {
let firstName = "iOS Geek"
self.first.append(firstName)
self.performSegue(withIdentifier: "MovetoSecVC", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MovetoSecVC"{
let secVC = segue.destination as! SecondVC
secVC.name = first
print(first) // it'll print here ["iOS Geek"]
}
}
// Your Second View Controller
class SecondVC: UIViewController {
var menu_vc : MenuViewController!
var name : [String]? // passing to this Array
override func viewDidLoad() {
super.viewDidLoad()
print(name!) // it'll print here ["iOS Geek"]
}
}

Swift 3, Successfully passed data but var returns nil when used

So here is my code from VC1 and passing the data to VC2.
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedArtist = artists[indexPath.item]
performSegue(withIdentifier: "artistToArtSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "artistToArtSegue" {
let artCollectionController = ArtCollectionController()
artCollectionController.artist = selectedArtist
artCollectionController.selectedArtist = selectedArtist
}
}
These codes here in VC2 will print the data
class ArtCollectionController: UICollectionViewController {
var artist = Artist() {
didSet{
print(artist.artistId ?? "did not work")
print(artist.name ?? "what name?")
}
}
var selectedArtist = Artist()
but when I use the the variable in these following test codes in VC2. They return a nil.
func fetchArtForArtist() {
guard let artistId = selectedArtist.artistId else {return}
print(artistId)
let fanRef = FIRDatabase.database().reference().child("art_ref").child(artistId)
fanRef.observeSingleEvent(of: .childAdded, with: { (snapshot) in
let artId = snapshot.key
print(artId)
// let dataRef = FIRDatabase.database().reference().child(artId)
// dataRef.observe(.value, with: { (snapshot) in
// let dictionary = snapshot.value as? [String: AnyObject]
// //let art =
// }, withCancel: nil)
}, withCancel: nil)
}
#IBAction func testButton(_ sender: UIBarButtonItem) {
print(selectedArtist.name ?? "no name")
print(12345)
}
override func viewDidAppear(_ animated: Bool) {
selectedArtist = artist
print(artist.name ?? "non")
print(selectedArtist.artistId ?? "no id")
}
override func viewDidLoad() {
super.viewDidLoad()
fetchArtForArtist()
selectedArtist = artist
print(artist.name ?? "non")
print(selectedArtist.artistId ?? "no id")
}
Im doing this in storyBoard. Im even using 2 vars seeing if there is a difference. I dont understand why the data is successfully passed to VC2 to a couple variables but when the variable is used it returns a nil. Please help.
The other responses are good, but I prefer a slightly different approach:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.destination {
case let artCollectionController as ArtCollectionController:
artCollectionController.artist = selectedArtist
artCollectionController.selectedArtist = selectedArtist
case let otherViewController as OtherViewController:
//Code for some other case
}
}
By using a switch statement, you have a prepareForSegue that will handle multiple different segues cleanly.
The case let construct is a cool trick that only executes that case if the variable in the switch can be case to the desired type. If it can be cast, it creates a local variable of the desired type.
I prefer deciding what code to execute based on the class of the destination view controller because it's less fragile than using the segue identifier. If you forget to set the segue identifier, or add a second segue later to the same type of view controller, or have a typo in the name of the identifier, that code won't work. If you have a typo in your class name, though, the compiler throws an error.
Because you set the artist property on a new instance of ArtCollectionController, which is destroyed upon the exit of the prepareForSegue function:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "artistToArtSegue" {
let artCollectionController = ArtCollectionController() // created
artCollectionController.artist = selectedArtist
artCollectionController.selectedArtist = selectedArtist
// destroyed here
}
}
Try this instead:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "artistToArtSegue",
let artCollectionController = segue.destination as? ArtCollectionController
{
artCollectionController.artist = selectedArtist
artCollectionController.selectedArtist = selectedArtist
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "artistToArtSegue" {
let artCollectionController = segue.destination as! ArtCollectionController
artCollectionController.artist = selectedArtist
artCollectionController.selectedArtist = selectedArtist
}
}
try this, you are creating one more ArtCollectionController instead of passing data to segue one

Resources