Question

I know that there are tutorials everywhere, but I can't figure this out for some reason. I have a tab bar controller. Each tab links to a navigation controller, which is segued to a view controller. So, 2 main view controllers (StatusVC and TransactionsVC).

In StatusVC, I have a text field. In TransVC, I have a table view. A person adds a cell to the table. Math is done behind the scenes. The cell values are added together (numbers). This information is sent back to StatVC for calculations and displaying of the data. I've already got the math part down. My question: how do I transfer the data between view controllers, and better yet, how do I store this data so that it doesn't get deleted on quit (NSUserDefaults probably)?

This can be broken down I suppose, the transferring of data, the saving of data, and the displaying of data when the tab is pressed and view is shown.

I'm hoping this is making sense. Anyway, here's the code I've got. You're looking at TranVC. User enters data into the table with an alert view. You are looking at part of the Alert View delegate methods. This is when the user enters data into a cell (presses done). Look for key areas with the ******* comments.

StatusViewController *statVC = [[StatusViewController alloc]init]; //*******init

            // Set the amount left in the budget
            NSString *amountToSpend = statVC.amountLeftInBudget.text;
            double budgetLabel = [amountToSpend doubleValue];

            NSString *lastItem = [transactions objectAtIndex:0];
            double lastLabel = [lastItem doubleValue];

            double totalValue = budgetLabel - lastLabel;

            NSString *amountToSpendTotal = [NSString stringWithFormat: @"%.2f", totalValue];

            statVC.amountLeftInBudget.text = amountToSpendTotal; //*******set text (but not save), either way, this doesn't work

            // Set the amount spent
            NSString *sum = [transactions valueForKeyPath:@"@sum.self"];
            double sumLabel = [sum doubleValue];

            NSString *finalSum = [NSString stringWithFormat:@"%.2f", sumLabel];

            //Set the amountSpent label
            statVC.amountSpent.text = finalSum;  //*******set text (but not save), either way, this doesn't work


            // The maxed out budget section
            if ([statVC.amountLeftInBudget.text isEqualToString: @"0.00"]) //*******set color (but not save), either way, this doesn't work

            {
                statVC.amountLeftInBudget.textColor = statVC.currencyLabel.textColor = [UIColor redColor];
            } else if ([statVC.amountLeftInBudget.text compare:@"0.00"] == NSOrderedAscending)
            {
                statVC.amountLeftInBudget.textColor = statVC.currencyLabel.textColor = [UIColor redColor];
            } else if ([statVC.amountLeftInBudget.text compare:@"0.00"] == NSOrderedDescending)
            {
                statVC.amountLeftInBudget.textColor = statVC.currencyLabel.textColor = [UIColor colorWithRed:23.0/255.0 green:143.0/255.0 blue:9.0/255.0 alpha:1.0];
            }

            if ([statVC.amountLeftInBudget.text compare:@"0.00"] == NSOrderedAscending)
            {
                // Create our Installation query
                UIAlertView *exceed;
                exceed = [[UIAlertView alloc]
                          initWithTitle: @"Budget Exceeded"
                          message: @"You have exceeded your budget amount"
                          delegate: self
                          cancelButtonTitle: @"Okay"
                          otherButtonTitles: nil];
                [exceed show];
            }

Any help with this would be amazing.

Was it helpful?

Solution

This is indeed a common question.

There are various solutions. The one I recommend is to use a data container singleton. Do a google search on the singleton design pattern in Objective C. You'll even find examples of it here on SO.

Create a singleton with properties for the values that you want to share. Then teach your singleton to save it's data. You can use user defaults, you can use NSCoding, you can extract the data to a dictionary and save it to a plist file in your documents directory, or various other schemes as well.

OTHER TIPS

Like Duncan suggested, a Singleton pattern might be the best route to go. If you place the shared data into a model class, you can create a class method that can be used to acquire a singleton object.

MyModel.m

@implementation MyObject

- (id) init
{
    return nil; // We force the use of a singleton. Probably bad practice?
}

// Private initializer used by the singleton; not included in the header file.
- (id)initAsSingleton {
    self = [super init];
    if (self) {
        // Initialize your singleton instance here. 
    }
    return self;
}

+ (MyModel *)sharedMyModel {
    static MyModel *myModel = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        myModel = [[MyModel alloc] initAsSingleton];
    });

    return myModel;
}

MyModel.h

@interface MyModel : NSObject

+ (MyModel *)sharedMyModel; // Singleton instance.

@end

This does not protect against you using [[MyModel alloc] init];. It returns a nil object which is probably poor programming on my end, but it does force you to use the singleton object instead. To use in each one of your view controllers, you just use the following line to grab the singleton instance.

MyModel *model = [MyModel sharedMyModel];

Store the data into it, and return to your other view controller and grab the singleton again. You'll have all of your data.

After thinking about it, you could also force the default initializer to just return your singleton instance like:

- (id)init {
    return [MyModel sharedMyModel];
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top