1

How to have pass the value of a selected tableView to a public variable that can be accessed by multiple ViewControllers? Currently, in didSelectRowAt, I define the row selected as portfolio doing let portfolio = structure[indexPath.row] Now how can I save this value to perhaps some sort of variable that makes it avalible to multiple view controller?

I don't just mean pushing the value to whichever view controller is being presented when the cell is pressed, I need it be available to view controller past the .pushViewController.

In the past I tried using userdefaults, but this is not appropriate for values that are constantly changing and are not permanen.

import UIKit

class ScheduledCell: UITableViewCell {

    @IBOutlet weak var ETALabel: UILabel!
    @IBOutlet weak var cellStructure: UIView!

    @IBOutlet weak var scheduledLabel: UILabel!
    @IBOutlet weak var testingCell: UILabel!
    @IBOutlet weak var pickupLabel: UILabel!
    @IBOutlet weak var deliveryLabel: UILabel!
    @IBOutlet weak var stopLabel: UILabel!
    @IBOutlet weak var topBar: UIView!


}

class ToCustomerTableViewController: UITableViewController, UIGestureRecognizerDelegate {

    var typeValue = String()

    var driverName = UserDefaults.standard.string(forKey: "name")!
    var structure = [AlreadyScheduledStructure]()


    override func viewDidLoad() {
        super.viewDidLoad()

        fetchJSON()


        //Disable delay in button tap
        self.tableView.delaysContentTouches = false

        tableView.tableFooterView = UIView()

    }


    private func fetchJSON() {
        guard let url = URL(string: "https://example.com/example/example"),
            let value = driverName.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)
            else { return }

        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.httpBody = "driverName=\(value)".data(using: .utf8)

        URLSession.shared.dataTask(with: request) { data, _, error in
            guard let data = data else { return }


            do {
                self.structure = try JSONDecoder().decode([AlreadyScheduledStructure].self,from:data)
                DispatchQueue.main.async {
                    self.tableView.reloadData()
                }
            }
            catch {
                print(error)
            }

            }.resume()

    }



    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return structure.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "scheduledID", for: indexPath) as! ScheduledCell
        let portfolio = structure[indexPath.row]
        cell.stopLabel.text = "Stop \(portfolio.stop_sequence)"
        cell.testingCell.text = portfolio.customer
        return cell

    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {


        let portfolio = structure[indexPath.row]
        let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "scheduledDelivery")

        print(portfolio.customer)
        controller.navigationItem.title = navTitle
        navigationController?.pushViewController(controller, animated: true)
    }


    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 200.0
    }

}
  • `how can I save this value to perhaps some sort of variable that makes it avalible to multiple view controller?`: you can store that value to a Singleton Object? or broadcast to other view controllers by using NSNotificationCenter? or if these view controllers are downstream from your navigation stack, then you can create an object and passing over to multiple pages? – HSG Jun 27 '19 at 03:28
  • Is broadcasting it using NSNotification Center effective for value that constantly change (selecting different row with different values) ? –  Jun 27 '19 at 03:30
  • IMO it would be fine of using NSNotificationCenter to broadcast changes of a value. Maybe you can consider using KVO instead? or a safer way is multicast delegate (https://github.com/jonasman/MulticastDelegate) – HSG Jun 27 '19 at 04:07
  • Would you say NSnotifications are better to use in this case than say Userdefaults? –  Jun 27 '19 at 04:18
  • Yes, NSUserDefaults is persistent storage, comparing to your case that the variable is in memory only? – HSG Jun 27 '19 at 04:24
  • Yes, the variable will change when the user selects a different row in my case –  Jun 27 '19 at 04:34

2 Answers2

1

You can use a function to pass an optional Value inside an extension, try the following:

From what I understood you want to pass values from your viewController and be able to get it from any other viewController..

extension UIViewController { 

  func passData(row: Int?) -> Int? {

    var myValue = Int()

    if row != nil {
        myValue = row!
    }

    return myValue
}

   } 

in this function you can Pass the value you want and also retrieve it. to pass data into the function simply use this :

passData(row: indexPath.row)

and if you want to retrieve the value of it from another viewController use this:

let myValue = passData(row: nil)

this way you could get the Data you pass from another viewController.. if that didn't work for you I'd suggest you use UserDefaults ..

I hope this could solve your problem.

Yasser
  • 265
  • 1
  • 8
  • I like your method, what are you’re thought on using NSNotifications to solve this issue? –  Jun 27 '19 at 05:28
  • I'm not sure, I didn't try that before. for me I think `extension` is a better way to do this. – Yasser Jun 27 '19 at 06:15
  • you can use NSNotifications but make sure you remove observer when not in use if not you will get crash – Vinodh Jun 27 '19 at 07:32
  • About your comment regarding UserDefaults; that is really wrong UserDefaults is used for storing long term data, overring the UserDefaults everytime a new row is selected is not good –  Jun 27 '19 at 16:19
0

You can use NSNotificationCenter and post value after selection and every subscribed controller will received a new value. For more info read this NSNotificationCenter addObserver in Swift