0

I am coding a Calorie Tracker app in which I have 3 view controllers. They are all hooked up to a tab bar controller in the storyboard.

  • Diet View Controller
  • Exercise View Controller
  • Home View Controller

Essentially what I want to do is to take the data from my Exercise view Controller and My Diet View Controller and display it on my Home View Controller. This is my code for viewDidLoad in my HomeViewController.m

    //Referencing both view controllers
MainViewController *mainViewController = [[MainViewController alloc] init];
ExerciseViewController *exerciseViewController = [[ExerciseViewController alloc] init];

//Doing the math
int totalCalsConsumed = mainViewController.totalLabel.text.intValue;
int totalCalsBurned = exerciseViewController.totalCalsBurned.text.intValue;
int totalAmountOfCalories = totalCalsConsumed - totalCalsBurned;

//display the data
NSString *totalAmtCalsText = [NSString stringWithFormat:@"%i", totalAmountOfCalories];
totalAmtOfCals.text = totalAmtCalsText;

Also, I cannot pass any data with segues because all my view controllers are hooked up to a tab bar, and there is no prepareForSegue method for tab bars.

All help is appreciated, and I would also like to know if I DESPERATELY HAVE TO use Core Date for this dilemma. For now I'm trying to dodge Core Date for it is a very advanced topic that I will touch upon in the future, but If I MUST use Core Data for this app I'll figure something out.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
doc92606
  • 691
  • 2
  • 11
  • 32
  • What is the difference between `MainViewController` and `HomeViewController`? Also why is it that you have not referenced the `DietViewController`? – Pavan Jan 09 '14 at 00:19
  • Sorry my MainViewController is the DietViewController – doc92606 Jan 09 '14 at 00:21
  • And is it the total Amount of calories that you want to pass DOWN to either the dietViewController and HomeViewController? – Pavan Jan 09 '14 at 00:21
  • You are NOT referencing both controllers, you're creating new ones with alloc init. To reference them use self.tabBarController.viewControllers -- that will give you an array of all the tab bar controller's view controllers. – rdelmar Jan 09 '14 at 00:22
  • I want to get an integer from my exercise view controller and from my diet view controller and mathematically use them in my home view controller. So would I get the exercise view controller's label like this?: self.tabBarController.viewControllers.ExerciseViewController.totalCalsBurned.text ? – doc92606 Jan 09 '14 at 00:25
  • Ok gotcha, that is not correct since you are accessing an array and array's objects are accessed using the objectForIndex method. Check my post in a minute to show you how to do that – Pavan Jan 09 '14 at 00:26
  • I just want to point out that core data is not the only alternative. UIDocument is pretty nice. It depends what you need! – ecsos Jan 09 '14 at 00:29
  • Interesting, I've only heard of core date for high end data management – doc92606 Jan 09 '14 at 00:30
  • @Pavan are you still there? – doc92606 Jan 09 '14 at 00:37
  • Yep, check my answer for you @doc92606 – Pavan Jan 09 '14 at 00:42

3 Answers3

1

Due to your strong desire to avoid Core Data - which I feel should be considered - I can provide a quick, perhaps dirty (maybe not) solution so that you can have data accessible through out your viewControllers.

Based on what youre doing it seems as though you want to access data from your tabbar view controllers.

One way of doing this is to have a data model in one single place which can be accessible by other view controllers. Like a server with a webservice or have a singleton that keeps your data in one place.

In your case, you want a quick solution, you can do this for now which works, as long as all the ViewControllers mentioned are in your tabBar

//Create variables
int totalCalsConsumed;
int totalCalsBurned;
int totalAmountOfCalories;

//All your view controllers are accessible from your tabBar like so
NSArray *myViewControllers = self.tabBarController.viewControllers;

//We iterate through the view controllers in the tabBar
for(int i = 0; i < [myViewControllers count]; i++){
    //This is the current view controller in the for loop execution
    id currentVC = [myViewControllers objectAtIndex:i];

    //Check if the currentVC variable is of type MainViewController
    if([currentVC isKindOfClass:[MainViewController class]]{
        //lets access the totalLabel property and store in variable
        totalCalsConsumed = ((MainViewController *)currentVC).totalLabel.text.intValue;
    }
    //Check if the currentVC variable is of type ExerciseViewController
    else if([currentVC isKindOfClass:[ExerciseViewController class]]){
        //if so lets now access the totalCalsBurned property and store in variable
        totalCalsBurned = ((ExerciseViewController *)currentVC).totalCalsBurned.text.intValue;
    }
}

//Doing the math
totalAmountOfCalories = totalCalsConsumed - totalCalsBurned;

//display the data
NSString *totalAmtCalsText = [NSString stringWithFormat:@"%d", totalAmountOfCalories];
totalAmtOfCals.text = totalAmtCalsText;

I haven't tested this as I just wrote this now, but it should be good from the get go. Code commenting is there for you understand whats going on. Pretty straight forward.

tip for you mate since youre developing a fitness app In the future, I do recommend something more persistent, where by data isnt lost if the application has quit, especially since you're creating a fitness app. I currently am using the BodyBuilding fitness app in my personal time, and have been frustrated at times when data was lost during my work out (sets information, exercises done with total reps for each set) only because the developers never bothered to store my data somewhere whilst I was doing my exercise, in case for when my battery died out.

Pavan
  • 17,840
  • 8
  • 59
  • 100
  • Awesome, Going to try this out right now and will be back in a sec! – doc92606 Jan 09 '14 at 00:42
  • There are only 2 errors in which totalCalsConsumed = currentVC.totalLabel.text.intValue says that property total label not found on object of type '_strong id'. This also says the same thing for totalCalsBurned. – doc92606 Jan 09 '14 at 00:44
  • does this mean i have to create an object for each view controller first like the MainViewController *mainViewController = [[MainView Controller alloc] init]; ? – doc92606 Jan 09 '14 at 00:47
  • No, In short, it means that those two properties are not found in an `id` class, in our case we have to cast the currentVC variable to their respective ViewControllers by doing something like `((MainViewController*)currentVC).whatever.whatever` and same goes for `((ExerciseViewController*)currentVC).whatever.whatever`. The reason we are using the `id` as our type for the currentVC is because during the for loop the Class Type of viewcontroller changes from `MainViewController` to `ExerciseViewController`. Just check the code again since ive updated it now. – Pavan Jan 09 '14 at 00:47
  • Lol the code works, but now my totalAmtOfCals label on my home page is at a constant 1095614535 xD – doc92606 Jan 09 '14 at 00:50
  • Ah, I tested your code separately on another app and it worked! I'm going to debug my app right now and figure out what's wrong :) – doc92606 Jan 09 '14 at 01:01
  • Yes @doc92606, WolfgangSchreurs is right. Lol sorry, I blindly copied your math code. – Pavan Jan 09 '14 at 01:02
  • Ok well great, you've got the essentials you need now to go away and have it all fixed. Goodluck with the fitness app. Let me know when its out ;) If i dont hear from you its because you became fat programming day and night on your seat most likely still stuck on this problem :P Have a good one. – Pavan Jan 09 '14 at 01:03
0

You could choose 1 of several approaches:

  1. You could create a Singleton and store/read all persistent data from this singleton. Singletons should be used with care though.
  2. You could use NSNotificationCenter to send out NSNotifications whenever some value changes. UIViewControllers can register to receive NSNotifications.
  3. You could store persistent data on the file system using CoreData or some other technology like NSUserDefaults or NSKeyedArchiver / NSKeyedUnarchiver.
  4. Perhaps a dependency injection method could be used as well. Creating an object in the app delegate and passing it to all related UIViewControllers. Use this object in the same way you'd use the singleton I mentioned as option 1.

There's probably more options that I can't remember at this current moment.

Alex Cio
  • 6,014
  • 5
  • 44
  • 74
Wolfgang Schreurs
  • 11,779
  • 7
  • 51
  • 92
0

Key value Coding , NSNotificationCentre and Delegates are preferred. But NSNotificationCentre is easiest in your case.

The UIViewController Home View Controller must add observer like this : Init :

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(methodToUpdate:) name:@"UPDATE_ME" object:(id)anyObject];

In delloc method :

[[NSNotificationCenter defaultCenter] removeObserver:self];

Post it from other 2 classes like on any UIButton action:

[[NSNotificationCenter defaultCenter] postNotificationName:@"UPDATE_ME" object:(id)anyObject];

Advantage of NSNotificationCentre is that they can add observers in multiple classes ..

Zeeshan
  • 4,194
  • 28
  • 32