0

I'm very new to iOS development and I know there have been questions like this asked, but I can't seem to pull out of those examples what I think I need.

I'm trying to teach this to myself by coding a very simple mortgage calculator. I have two views, MortgageCalculatorViewController where the user enters the loan value, term and interest; and the ResultsViewController where this information is redisplayed, with the monthly payment, in labels. My current issue is I can't seem to figure out how to relay the calculated monthly payment value to the ResultsViewController.

I named the segue showResultsSegue.

In MortgageCalculatorViewController:

#import "MortgageCalculatorViewController.h"
#import "ResultsViewController.h"

@interface MortgageCalculatorViewController ()

@end

@implementation MortgageCalculatorViewController

NSString *paymentText;

-(IBAction)calculateMonthlyPayment
{
    float rate = (self.interestRate.text.floatValue / 12) / 100;
    long term = self.termInYears.text.integerValue;
    float principle = self.loanAmount.text.floatValue;

    float termedRate = pow((1 + rate), term);
    float payment;

    payment = (principle * rate * termedRate) / (termedRate - 1);

    paymentText = [NSString stringWithFormat:@"%f", payment];
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if([segue.identifier isEqualToString:@"showResultsSegue"]){
        ResultsViewController *controller = (ResultsViewController *)segue.destinationViewController;
        controller.paymentLabel.text = paymentText;
    }
}

@end

And in ResultsViewController:

@interface ResultsViewController : UIViewController

@property (nonatomic) IBOutlet UILabel *loanAmountLabel;
@property (nonatomic) IBOutlet UILabel *termInYearsLabel;
@property (nonatomic) IBOutlet UILabel *interestRateLabel;
@property (nonatomic) IBOutlet UILabel *paymentLabel;

-(IBAction)close;

@end

I've guided this approach on the information I found in Passing Data between View Controllers, but I'm still seeing no change after the segue.

Any help would be appreciated. Thanks.

Community
  • 1
  • 1
Anthony
  • 3
  • 1

3 Answers3

1
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if([segue.identifier isEqualToString:@"showResultsSegue"]){
        ResultsViewController *controller = (ResultsViewController *)segue.destinationViewController;
        controller.paymentLabel.text = paymentText;
    }
}

When preparing for a segue, the view has probably not been loaded, so paymentLabel is nil. Instead, declare a paymentText property on ResultsViewController and assign that value to paymentLabel in viewDidLoad.

New prepareForSegue:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if([segue.identifier isEqualToString:@"showResultsSegue"]){
        ResultsViewController *controller = (ResultsViewController *)segue.destinationViewController;
        controller.paymentText = paymentText;
    }
}

Implementation for ResultsViewController:

@interface ResultsViewController : UIViewController

@property(copy, nonatomic) NSString *paymentText;

@end

@implementation ResultsViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.paymentLabel.text = self.paymentText;
}

@end
Austin
  • 5,625
  • 1
  • 29
  • 43
0

It's likely that your ResultsViewController has not initialized it's view elements, including the paymentLabel yet. Try explicitly calling view before setting the label text like so:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if([segue.identifier isEqualToString:@"showResultsSegue"]){
        ResultsViewController *controller = (ResultsViewController *)segue.destinationViewController;
        [controller view];
        controller.paymentLabel.text = paymentText;
    }
}

Calling view will cause the view controller to load it's view elements, hence letting you set the label's text properly.

JJC
  • 1,346
  • 10
  • 10
0

By far the easiest why to do this without using delegates, singletons or as mentioned above using the prepareForSegue, is using NSUserDefaults.

Save string:

[[NSUserDefaults standardUserDefaults] setObject:paymentText forKey:@"payment"];
[[NSUserDefaults standardUserDefaults]synchronize];

Read string:

NSString *readPaymentString = [[NSUserDefaults standardUserDefaults] stringForKey:@"payment"];

What you basically need to do here is to use the save code I provided in one view and the read code in the second view, simple.

I hope it makes sense.

fs_tigre
  • 10,650
  • 13
  • 73
  • 146