0
var messageViewController: MessageViewController?
var settingsViewController: SettingsViewController?
var otherViewController: OtherViewController?
override func viewDidLoad() {
   messageViewController = //the first one
   settingsViewController = //the second one
   otherViewController = //the third one
}

And then later down the code, I can call methods in those controllers when needed.

messageViewController.reloadData()
TIMEX
  • 259,804
  • 351
  • 777
  • 1,080

4 Answers4

1

try this,

let firstViewController = self.viewControllers![0] as FirstViewController
let secondViewController = self.viewControllers![1] as SecondViewController

and so on..

bhavesh
  • 109
  • 14
1

The viewControllers property of UITabBarController is an array of references to each content view controller. If you know exactly which controller is at each index, you can just assign your variables from this array:

override func viewDidLoad() {
    super.viewDidLoad()
    messageViewController = viewControllers![0] as! MessageViewController
    settingsViewController = viewControllers![1] as! SettingsViewController
    otherViewController = viewControllers![2] as! OtherViewController
}

Or even make the variables computed properties:

var messageViewController: MessageViewController { return viewControllers![0] as! MessageViewController }
var settingsViewController: SettingsViewController { return viewControllers![1] as! SettingsViewController }
var otherViewController: OtherViewController { return viewControllers![2] as! OtherViewController }
Stuart
  • 36,683
  • 19
  • 101
  • 139
  • When I do the computed property, it says: ```'AnyObject' is not convertible to 'LobbyViewController'; did you mean to use 'as!' to force downcast?``` And then, when I make the suggestion and add the exclamation, ```var lobbyVC: LobbyViewController { return viewControllers[0] as! LobbyViewController }```, the error says: ```Cannot subscript a value of type '[AnyObject]?' with an index of type 'Int'``` – TIMEX Apr 21 '15 at 07:58
  • @TIMEX Sorry, I've corrected some errors. The `viewControllers` array is optional, but provided you created the tab bar correctly it will not be `nil` so you can force unwrap it with `!`. You must also cast to the appropriate view controller class, as for legacy reasons `viewControllers` is an array of `AnyObject`s. – Stuart Apr 21 '15 at 08:02
  • Thanks! Do you think I need to deal with delegates? Or is this method good enough when I want to call methods from those VCs? – TIMEX Apr 21 '15 at 08:03
  • Delegates are not necessary if all you want to do is call methods on your content view controllers based on information received in the tab bar controller (e.g. the tab bar controller knows when any/all content needs updating, so it tells its child VCs). I would start looking at delegation if the roles are reversed, so a child VC receives some information and needs to tell the parent (tab bar) VC so it can act on it. Delegation is about passing information _up_ the hierarchy, passing information _down_ can be done by calling methods on properties. – Stuart Apr 21 '15 at 08:09
0

You will have to use delegate protocol to send variables or call methods over different View Controllers. I already answered this in another post, so please check out my answer on how to do this:

How to pass a variable from a class to another?.

Community
  • 1
  • 1
Fengson
  • 4,751
  • 8
  • 37
  • 62
  • I don't think they are looking to pass variables back from the view controllers, rather they want to assign each content view controller _to_ a variable in the tab bar controller. – Stuart Apr 21 '15 at 07:45
0

Another solution(depend on your needs) is to implement one(whoever calls reloadData) to many(all view controllers) relationship. The easiest way to accomplish this is via notifications. You can read more about them here.

In this way your tabBar doesn't have to know about it's child public methods, and moreover doesn't care who listens for it's notifications(it may be even tableview, cell or whatever).

hris.to
  • 6,235
  • 3
  • 46
  • 55