How to send an array of struct between two view controllers? - swift

Im trying to send an array "ranking" of Struct between two VC after tapping the "rankingButton". I don't know what to code in the second vc to get and manipulate the array.
First VC:
struct TopPoint{
let user: String
let points: Int
var position: Int
}
var ranking: [TopPoint] = []
override func viewDidLoad() {
super.viewDidLoad()
let user1 = TopPoint(user: "fran", points: 1324, position: 1)
ranking.append(user1)
}
#IBAction func rankingButton(_ sender: Any) {
let vc = TopUserTableViewController(nibName: "TopUserTableViewController", bundle: nil)
vc.ranking = ranking
navigationController?.pushViewController(vc, animated: true)
}
Second VC:
class TopUserTableViewController: UITableViewController {
var ranking = [TopPoint]()
override func viewDidLoad() {
super.viewDidLoad()
}
//what to code to get the array?
}

Once your secondVC pushed, you can directly access the array in the secondVC. Because you set its ranking property equal to ranking in the firstVC For example consider having a method to iterate through array elements and print user of each struct element inside your array. You can do it by:
class TopUserTableViewController: UITableViewController {
var ranking: [TopPoint]!
override func viewDidLoad() {
super.viewDidLoad()
iterateElements()
}
func iterateElements() {
ranking.forEach { (element) in
print(element.user)
}
}
}
You could also access directly inside your viewDidLoad, I added iterateElements method as reference, access directly in viewDidLoad as:
override func viewDidLoad() {
super.viewDidLoad()
ranking.forEach { (element) in
print(element.user)
}
}

viewDidLoad() is too early in the lifecycle. Just move your code:
func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
ranking.forEach { (element) in print(element.user) } }
}

Related

Access var from a new swift file from a class

I have this viewcontroller class:
class ThirdScreenViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
var number = 1
#IBAction func pressed(_ sender: UIButton) {
number = 2
}
}
And I have a different swift file. (Not another View Controller Class)
var newNumber = ThirdScreenViewController.number
This doesn't work. How can I access in my new swift file to this variable (2) from an other View Controller Class?
The simplest solution would be to make the property static:
class ThirdScreenViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
static var number = 1
#IBAction func pressed(_ sender: UIButton) {
ThirdScreenViewController.number = 2
}
}
After that you should be able to call the variable as indicated in your example:
var newNumber = ThirdScreenViewController.number
But using static properties in such a case is not the best practice.

No Storyboard Member within my ViewController when calling another view controller

When I run my code below within my view controller
import UIKit
class SecondViewController: UIViewController {
let fifthVC = self.storyboard?.instantiateViewController(withIdentifier: "fifthVC") as? FifthViewController
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func twentyLife() {
fifthVC.lifePointsInt = 20
}
#IBAction func thirtyLife() {
fifthVC.lifePointsInt = 30
}
#IBAction func fortyLife() {
fifthVC.lifePointsInt = 50
}
}
I am getting error
Value of type '(SecondViewController) -> () -> SecondViewController'
has no member 'storyboard'
How can I fix this?
I don't know what you are trying to do here but to remove that error , you should call the following line inside some function
let fifthVC = self.storyboard?.instantiateViewController(withIdentifier: "fifthVC") as? FifthViewController
You can either call it in viewDidLoad or you can make a separate function and call it. But first you need to define fifthVC variable in view controller.
var fifthVC:UIViewController?
Then inside viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
fifthVC = self.storyboard?.instantiateViewController(withIdentifier: "fifthVC") as? FifthViewController
}

passing data from one view controller to other showing nil

//first viewController where Tvshowpath contains data. I print Tvshowpath2 in this viewController data is printed//
#objc var TvshowPath = NSDictionary()
override func viewDidLoad()
{
super.viewDidLoad()
let playerPage =
self.storyboard?.instantiateViewController(withIdentifier:
"playerLayer")
as! PlayerLayerViewController
playerPage.TvshowPath2 = TvshowPath
print(playerPage.TvshowPath2)
self.navigationController?.pushViewController(playerPage, animated: true)
}
//In the second viewController where Tvshowpath2 data getting nil
#objc var TvshowPath2 = NSDictionary()
override func viewDidLoad()
{
super.viewDidLoad()
print(TvshowPath2)
}

How I can load self.navigationController before `viewDidLoad` called

I want to do some stuff before the view controller calls viewDidLoad. I call loadViewIfNeeded() but self.navigationController is still nil. How can I load it?
AppDelegate.swift
func someMethod() {
var viewController = Storyboard.instantiate()
let viewModel = SomeViewModel()
vc.bind(to: viewModel)
}
BindableType.swift
protocol BindableType {
associatedtype ViewModelType
var viewModel: ViewModelType! { get set }
func bindViewModel()
}
extension BindableType where Self: UIViewController {
mutating func bind(to model: Self.ViewModelType) {
viewModel = model
loadViewIfNeeded()
// PROBLEM HERE: navigationController is nil, but view have been loaded
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationItem.largeTitleDisplayMode = .automatic
bindViewModel()
}
}
SomeViewController.swift
class SomeViewController: BindableType {
override func viewDidLoad() {
super.viewDidLoad()
// navigationController?.navigationBar.prefersLargeTitles = true
// navigationController?.navigationItem.largeTitleDisplayMode = .automatic
}
func bindViewModel() {
...
}
}
I found the problem. I must put the line with pushing controller above viewController.bind(to: viewModel)
self.navigationViewController.pushViewController(viewController, animated: true)
viewController.bind(to: viewModel)

Swift Transferring data to the first view by pressing the "Back" button

Hello friends . Navigation control to the second screen. I need to go
to the one screen with the button(Sonucları Listele) on the second screen and I have to
make the number on the first screen to "2"
image 1
image 2
First View
class KonularViewController: UIViewController {
var number : Int?
#IBAction func barButtonKonuEkle(_ sender: Any) {
let childViewController = storyboard?.instantiateViewController(withIdentifier: "KonuEkleViewController") as! KonuEkleViewController
navigationController?.pushViewController(childViewController, animated: true)
}
}
Second View
class AramaViewController: UIViewController {
#IBOutlet weak var btn1: UIButton!
#IBOutlet weak var btn2: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
btn1.isSelected = true
}
#IBAction func btnListele(_ sender: Any) {
//First View "Number" variable on the first screen will be 2
}
#IBAction func btn_box(sender: UIButton) {
if sender.titleLabel?.text == "En Yeniler"
{
btn1.isSelected = true
btn2.isSelected = false
}
else
{
btn2.isSelected = true
btn1.isSelected = false
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
One strategy would be to have a 3rd class that is your Model, which can hold state.
class Model {
static let shared = Model()
var count: Int = 1
}
class AramaViewController: UIViewController {
#IBAction fund btnListele(_ sender: Any) {
Model.shared.count += 1
//First View "Number" variable on the first screen will be 2
}
class KonularViewController: UIViewController {
override func viewWillAppear(animated:Bool) {
super.viewWillAppear(animated: animated)
numberView.text = "\(Model.shared.count)" //display your number here
}
}
Another Option
Reach back in the Navigation Controller View Controllers array to the previous view and set a property. This is a bit more fragile.
class KonularViewController: UIViewController {
var count: Int = 1
override func viewWillAppear(animated:Bool) {
super.viewWillAppear(animated: animated)
numberView.text = "\(count)" //display your number here
}
}
class AramaViewController: UIViewController {
#IBAction fund btnListele(_ sender: Any) {
let numberOfViews = navigationController.viewControllers.count
if count > 1, let previousViewController = self.navigationController.viewControllers[numberOfViews-2] as? KonularViewController
previousViewController.count += 1
//First View "Number" variable on the first screen will be 2
}
Assuming KonularViewController identifier is "KonularViewController".
In AramaViewController:
#IBAction func btnListele(_ sender: Any) {
//First View "Number" variable on the first screen will be 2
let konularViewController = storyboard?.instantiateViewController(withIdentifier: "KonularViewController") as! KonularViewController
konularViewController.number = 2
navigationController?.pushViewController(childViewController, animated: true)
}