Search code examples
iosswiftuiviewcontrollermacos-carbon

Swift - How to call method from a specific instance?


I am currently developing an iOS app using the CarbonKit library for navigation. I currently have a UITableView in the first tab, and I want to programatically navigate to another tab when a cell is selected.

I have implemented the following function under my main CarbonKit view controller:

import CarbonKit

class ViewController: UIViewController, CarbonTabSwipeNavigationDelegate {


    func carbonTabSwipeNavigation(carbonTabSwipeNavigation: CarbonTabSwipeNavigation, viewControllerAtIndex index: UInt) -> UIViewController      {

        switch index {
        case 0:
            return self.storyboard!.instantiateViewControllerWithIdentifier("AircraftViewController") as! AircraftViewController
        case 1:
            return self.storyboard!.instantiateViewControllerWithIdentifier("LoadController") as! LoadController
        case 3:
            return self.storyboard!.instantiateViewControllerWithIdentifier("SettingsController") as! SettingsController
        default:
            return self.storyboard!.instantiateViewControllerWithIdentifier("ViewControllerOne") as! ViewControllerOne
        }   
    }

    func navigate(index: UInt) {
        carbonTabSwipeNavigation.setCurrentTabIndex(index, withAnimation: true)  
    }

}

setCurrentTabIndex is the function provided by the library to programatically switch tabs.

In my UITableViewController I have the following:

import UIKit
import CarbonKit

class SecondViewController: UITableViewController {

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        \\ First Attempt
        (ViewController() as CarbonTabSwipeNavigationDelegate).navigate(2)

        \\ Second Attempt
        let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("controller") as! ViewController
        viewController.navigate(2)
   }

}

I understand that with my first attempt I created a new instance of ViewController and my second attempt didn't select the instance I was hoping for.

How can I best activate the method in the first instance of ViewController from SecondViewController?


Solution

  • Start by adding a CarbonTabSwipeNavigation property to your SecondViewController class, so you will have access to your navigation provider:

    import UIKit
    import CarbonKit
    
    class SecondViewController: UITableViewController {
        weak var carbonNavigation : CarbonTabSwipeNavigation?;
    
        override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
           if let carbonNav = self.carbonNavigation {
               carbonNav.setCurrentTabIndex(index, withAnimation: true)
           }
       }
    
    }
    

    Next up we need to set that carbonNavigation property, so it will be available for use. It looks like your CarbonTabSwipeNavigationDelegate is a nice place to do that. On a side note, I don't see your SecondViewController ever being returned by your delegate - is that intended?

    import CarbonKit
    
    class ViewController: UIViewController, CarbonTabSwipeNavigationDelegate {
    
    
        func carbonTabSwipeNavigation(carbonTabSwipeNavigation: CarbonTabSwipeNavigation, viewControllerAtIndex index: UInt) -> UIViewController      {
    
            switch index {
            case 0:
                let aircraftVC = self.storyboard!.instantiateViewControllerWithIdentifier("AircraftViewController") as! AircraftViewController
                aircraftVC.carbonNavigation = carbonTabSwipeNavigation
                return aircraftVC
            case 1:
                // do something similar, instantiate view controller, set navigation property
                return self.storyboard!.instantiateViewControllerWithIdentifier("LoadController") as! LoadController
            case 3:
                // do something similar, instantiate view controller, set navigation property
                return self.storyboard!.instantiateViewControllerWithIdentifier("SettingsController") as! SettingsController
            default:
                // do something similar, instantiate view controller, set navigation property
                return self.storyboard!.instantiateViewControllerWithIdentifier("ViewControllerOne") as! ViewControllerOne
            }   
        }
    
        func navigate(index: UInt) {
            carbonTabSwipeNavigation.setCurrentTabIndex(index, withAnimation: true)  
        }
    }
    

    You could also add a ViewController property instead of a CarbonTabSwipeNavigation and expose all of the methods you need from Carbon as methods in ViewController. That would mean changing the type of the property declaration and setting it to self instead of carbonTabSwipeNavigation.