-2

I'm new to iOS development and trying to get a grasp on objective c. I'm having trouble passing info between view controllers. I've played with this code using an integer and a NSString and it worked, so that tells me the VCs are talking to each other and the problem has something to do with the variables. dataString consists of timeString and dateString which work fine in the first view controller. Then when the string is passed to SecondViewController they each have null values. At the bottom of the page I have the NSLog output. Can anyone see what I'm missing or what I'm doing wrong?

The first view controller .h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController {
    NSTimer *time;
    NSString *dateString;
    NSString *timeString;
    int milliseconds;
    int seconds;
    int minutes;
 }
 - (IBAction)startButton:(UIButton *)sender;
 - (IBAction)finishButton:(UIButton *)sender;

 @property (retain) NSString *dataString; //string that will be passed 

 @property (strong, nonatomic) IBOutlet UILabel *timer;
 @property (strong, nonatomic) IBOutlet UIButton *button;
 @property (strong, nonatomic) IBOutlet UIButton *finish;

-(NSString *)getData; //I'm not sure why I need this here
@end 

First view controller .m

 #import "ViewController.h"
 #import "SecondViewController.h"
 @interface ViewController ();

 @end

 @implementation ViewController

 - (IBAction)startButton:(UIButton *)sender {
     //timer interval increments by milliseconds in updateTimer
     time = [NSTimer scheduledTimerWithTimeInterval:.01 target:self 
         selector:@selector(updateTimer) userInfo:nil repeats:YES];
     NSDate *date = [NSDate date];
     dateString = [self getDate: date]; //saves date and time the button was pressed 
 }

-(void)updateTimer {
    milliseconds += 1;
    if (milliseconds == 99){
        seconds += 1;
        milliseconds = 0;
    }
    if (seconds == 59){
        minutes += 1;
        seconds = 0;
    }
    timeString = [NSString stringWithFormat: @"%02i:%02i.%02i", minutes, seconds, milliseconds]; //formats display time in string
    self.timer.text = timeString;
}

-(NSString *)getDate : (NSDate *)date{
    date = [NSDate date]; //updates object with current date
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"MMM dd, yyyy hh:mm a"]; //formats date
    dateString = [dateFormatter stringFromDate:date]; //converts date object to string
    return dateString;
}

- (IBAction)finishButton:(UIButton *)sender {
    //button navigates to next view controller
    if (seconds > 0){
        [self getData]; //print current values before trying to pass
    }
    milliseconds = 0; //resets timer
    seconds = 0;
    minutes = 0;
    self.timer.text = @"00:00.00";
}

 //getter method do send string to next view controller 
-(NSString *)getData{
    dataString = [NSString stringWithFormat:@"%@ on %@", timeString, dateString]; //format data
    NSLog(@"%@ %@", dateString, timeString); //to double check values
    return dataString;
}

@end

Second view controller .h

#import <UIKit/UIKit.h>
#import "ViewController.h"

@interface dataScreenViewController : UIViewController {
    NSString *string; //string that I'm trying to pass
    ViewController *information //object for view controller class 
}
- (IBAction)press:(UIButton *)sender; //button to display string 
@end  

second view controller .m

#import "SecomdViewController.h"
#import "ViewController.h"

@interface SecondViewController ()

@end

- (void)viewDidLoad {
    [super viewDidLoad];
    information = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
}

- (IBAction)press:(UIButton *)sender {
    string = [information getData];
    NSLog(@"%@", string); //prints the string
} 

The NSLog output:

2017-12-29 12:47:49.792138-0800 MyFirstProject[6659:333408] Dec 29, 2017 12:47 PM 00:01.50

2017-12-29 12:47:52.499692-0800 MyFirstProject[6659:333408] (null) (null)

2017-12-29 12:47:52.499910-0800 MyFirstProject[6659:333408] (null) on (null)

Since the first print out has the correct information I assume everything is working correctly in the first VC, but then information in the variables in the string gets lost when I pass it.

EDIT: Here is the example of the ViewControllers talking one another to pass an int and a string. I just made the change in the getData method:

-(NSString *)getData{
    NSString *string = @"This is a string";
    string = [NSString stringWithFormat:@"%i on %@", 3, string];
    return string;
}

And then I still access it the same way in the second view controller:

- (IBAction)press:(UIButton *)sender {
    NSString *string = [information getData];
    NSLog(@"%@", string); 
}

And then the output is:

2017-12-30 09:07:40.764295-0800 MyFirstProject[8435:460529] 3 on This is a string

kreed
  • 61
  • 5
  • This line `information = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];` instantiates a whole new ViewController from the nib file which is not in use anywhere other than as your variable. It is not a reference to any other instance of ViewController you may have in use. So you get the default values. – Upholder Of Truth Dec 29 '17 at 21:19
  • The lazy approach would be a singleton/global storage for the data. The correct approach would be to have a property on #2 and then in #1 implement prepareForSegue method to assign data to that property on #2 before its view lifecycle starts. – ghostatron Dec 29 '17 at 22:01
  • @UpholderOfTruth, I can use the same code to pass an int or normal string so I thought that the ViewController object was working correctly. Do you know why the ViewController object would be acting differently in the current scenario? – kreed Dec 30 '17 at 00:43
  • @ghostatron, could you elaborate a little on how to use prepareForSeque in this situation? The apple developer docs aren't helping much – kreed Dec 30 '17 at 00:45
  • Show the code that you use for the Int and 'normal' String making sure that it is really doing what you think it is doning. – Upholder Of Truth Dec 30 '17 at 08:46
  • @UpholderOfTruth, I added an edit at the bottom with an example – kreed Dec 30 '17 at 17:18
  • @ghostatron, I got it to work with the prepareForSegue method. Thanks! – kreed Dec 30 '17 at 18:27

1 Answers1

1

Your second view controller creates a new and inactive/dead ViewController object called information. And, you don't call any methods on information that would initialize its date variables.

So information's timeString and dateString are not initialized. Uninitialized variables are NULL in Objective-C. That's why you see (null) in the output.

Assuming that you need only one ViewController object, which you want to use in the second view controller. If that's the case you must pass a reference of your ViewController to your second view controller.

meaning-matters
  • 21,929
  • 10
  • 82
  • 142