10 Replies
      Latest reply on Jul 2, 2019 8:57 PM by John368
      John368 Level 1 Level 1 (0 points)

        Hi everyone,

         

        I try to pass data from View Controller through Tab Bar Controller and Navigation Controller to Table View Controller. Screenshot of storyboard is bellow.

         

        https://drive.google.com/open?id=1GW6gaDxfK1zaEOk2aPE8izkS5B67ldZL

         

        My code is next:

         

        1. Send data from View Controller

         

        @IBAction func addToCarButton(_ sender: UIButton) {
               
                tabBarController?.selectedIndex = 1
               
                let navVC = tabBarController?.viewControllers![1] as! UINavigationController//
                let cartTableViewController = navVC.topViewController as! CartTableViewController
        
                cartTableViewController.titleItem = titleLabel.text
                cartTableViewController.image = SomeImage(photo: imageView.image!)
            }

         

        2. Get data in Table View Controller

         

        import UIKit
        
        class CartTableViewController: UITableViewController {
           
            // MARK: - Store data
            // Create variables for receiving data (title and data from image) from VC
            var titleItem: String?
            var image: SomeImage?
           
            // Create shopping cart - array of selected items
            var cartItems = [Cart]()
            var cartItem: Cart?
            
            override func viewDidLoad() {
                super.viewDidLoad()
            }
            
            override func viewWillAppear(_ animated: Bool) {
               
                //Load data from archive file
                cartItems = Cart.loadFromFile()
               
                // Create a new item
                if titleItem != nil, image != nil {
                    print("titleItem in Cart View Appear - \(String(describing: titleItem))")
                    cartItem = Cart(title: titleItem!, image: image!)
                }
               
                // Add new item to shopping cart
                if cartItem != nil {
                    cartItems.append(cartItem!)
                    
                }
               
                tableView.reloadData()
            }
           
        
            // MARK: - Table view data source
        
            override func numberOfSections(in tableView: UITableView) -> Int {
                return 1
            }
        
            override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                return cartItems.count
            }
        
           
            override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
               
                let cell = tableView.dequeueReusableCell(withIdentifier: "SecondCell", for: indexPath)
               
                // Pass title to cell
                cell.textLabel?.text = cartItems[indexPath.row].title
               
                // Retrieve image from array of archive file and convert from Data to UIImage format
               let image = UIImage(data: cartItems[indexPath.row].image.photo)
                // Pass image to cell:
                cell.imageView?.image = image
        
                return cell
            }
           
           
            // MARK: - Save data to archieve file
            override func viewWillDisappear(_ animated: Bool) {
               
                Cart.saveToFile(cartItems: cartItems)
                tableView.reloadData()
            }
           
            // Clear cart
            @IBAction func clearCartButton(_ sender: UIBarButtonItem) {
                cartItems.removeAll()
                tableView.reloadData()
            }

         

        But data are appear only after second click. I.e., I add item 1 and cart is empty. When I add item 2, cart has item 1. If then I add item 3, card has item 1 and item 2, and go on.

         

        I have done link bellow on gif that shows how it works.

         

        https://drive.google.com/open?id=1_ilwKHXTRBT250zB4At7UsbWJ09fQARl

         

        I tried to use different options, but I can not understand what is happening here.

         

        Could you give me advice how to fix it?

        • Re: How to pass data through TabBarController?
          Claude31 Level 8 Level 8 (6,395 points)

          How do you transition from the detail (where you pick a bouquet) after taping AddToCart to the tableView ?

            • Re: How to pass data through TabBarController?
              John368 Level 1 Level 1 (0 points)

              This is a transition:

               

              tabBarController?.selectedIndex = 1

               

              And this is a data passing:

               

              let navVC = tabBarController?.viewControllers![1] as! UINavigationController//
              let cartTableViewController = navVC.topViewController as! CartTableViewController
              
              cartTableViewController.titleItem = titleLabel.text
              cartTableViewController.image = SomeImage(photo: imageView.image!)
                • Re: How to pass data through TabBarController?
                  Claude31 Level 8 Level 8 (6,395 points)

                  I am not sure how it works, but could you try calling selectedIndex after:

                   

                  @IBAction func addToCarButton(_ sender: UIButton) {
                         
                          let navVC = tabBarController?.viewControllers![1] as! UINavigationController
                          let cartTableViewController = navVC.topViewController as! CartTableViewController
                  
                          cartTableViewController.titleItem = titleLabel.text
                          cartTableViewController.image = SomeImage(photo: imageView.image!)
                         
                          tabBarController?.selectedIndex = 1
                  
                      }
                    • Re: How to pass data through TabBarController?
                      John368 Level 1 Level 1 (0 points)

                      Yes, it works. Thank you very much!

                       

                      Could I ask you one question more? If you had a task to transfer data in this way, what code would you use?

                        • Re: How to pass data through TabBarController?
                          Claude31 Level 8 Level 8 (6,395 points)

                          So, the reason was :

                          - when you change selectedIndex, you call instantly the destView and its viewWillLoad

                          - before cartTableViewController.titleItem and image are set

                          - So, you don't see them at this time

                          - But then data will be saved

                           

                          It is the same when you performSegue: you must call it after data are set.

                           

                          For your code, I would keep it as is.

                          just change tha name of the func from addToCarButton to addToCartButton

                           

                          Don't forget to close the thread by marking the corrct answer.

                          Good continuation.

                            • Re: How to pass data through TabBarController?
                              Claude31 Level 8 Level 8 (6,395 points)

                              If you have a lot of data to transfer, you could define a struct to hold it, to transfer in a single call instead of multiple items. It does not change a lot, but easier to use and maintain

                               

                              Here, would be Cart (f I guess correctly how you defined it

                               

                              struct Cart {
                                  var title: String
                                  var image: SomeImage
                              }

                              Then:

                               

                              @IBAction func addToCarButton(_ sender: UIButton) {

                                      let navVC = tabBarController?.viewControllers![1] as! UINavigationController//
                                      let cartTableViewController = navVC.topViewController as! CartTableViewController
                              
                                      let newItem = Cart(title: titleLabel.text, image; SomeImage(photo: imageView.image!))
                                      //  cartTableViewController.titleItem = titleLabel.text
                                      // cartTableViewController.image = SomeImage(photo: imageView.image!)
                                      cartTableViewController.newItem = newItem
                                      tabBarController?.selectedIndex = 1
                              
                                  }

                               

                              class CartTableViewController: UITableViewController {
                              
                                  // MARK: - Store data
                                  // Create variables for receiving data (title and data from image) from VC
                                  //  var titleItem: String?
                                  // var image: SomeImage?
                                  var newItem: Cart?
                              
                                  // Create shopping cart - array of selected items
                                  var cartItems = [Cart]()
                                  // Does not seem to be needed     var cartItem: Cart?
                              
                                  override func viewDidLoad() {
                                      super.viewDidLoad()
                                  }
                               
                                  override func viewWillAppear(_ animated: Bool) {
                                  
                                      //Load data from archive file
                                      cartItems = Cart.loadFromFile()
                                  
                                      // Create a new item
                              /* NOT needed
                                       if titleItem != nil, image != nil {
                                          print("titleItem in Cart View Appear - \(String(describing: titleItem))")
                                          cartItem = Cart(title: titleItem!, image: image!)
                                      }
                              */
                                  
                                      // Add new item to shopping cart
                                      if newItem != nil {
                              
                                   //    if cartItem != nil {
                                          // cartItems.append(cartItem!)
                                          cartItems.append(newItem!)
                                      }
                                  
                                      tableView.reloadData()
                                  }
                              • Re: How to pass data through TabBarController?
                                John368 Level 1 Level 1 (0 points)

                                "just change tha name of the func from addToCarButton to addToCartButton"

                                 

                                Yeah, and AddToCar is well too