Search code examples
iosuiviewcontrollersharesegueviewdidload

iOS problems sharing data between view controllers


I'm having problems passing data between two view controllers.

I've seen two ways to do this.

One involves implementing prepareForSeque: in the segue's source view controller and another involves setting properties in the viewDidLoad: method of the segue's destination view controller.

e.g.-

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"toEmailReservationViewController"]) {
        FLSendEmailViewController *controller = (FLSendEmailViewController     *)segue.destinationViewController;
        if (!controller.startDateField.text) {

            controller.startDateField.text = @"today";
        }

    }
}

and

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.startDateField.text = ((FLViewController   *)self.presentingViewController).startDate;
}

I've got these to work on simple apps using two UIViewController. However, I can't get them to work on an app that has a UITabViewController connected to some UINavigationViewController connected to custom subclasses of UIViewController. When I click the button to perform the push seque, I get to the view I want, but the startDateField.text doesn't have the text from the segue's source view controller.

Why are these methods of sharing data not working with the tab controller and navigation controller setup?

I noticed that in prepareForSegue: I can't set controller.startDateField.text; as shown when I try to set it and use NSLog to display it. Could this be the problem? Is it possible that the property controller.startDateField.text doesn't exist yet?

I'm trying to grab the date from a datePicker in an instance of FLViewController, store this date in the property NSString *startDate, and in an instance of FLSendEmailViewController set NSString *startDateField.text to the `NSString *startDate'.

Here are the UIViewController subclasses I created:

FLViewController.h

#import <UIKit/UIKit.h>

#import "FLSendEmailViewController.h"

// import frameworks to use ad
@import AddressBook;
@import AddressBookUI;

@interface FLViewController : UIViewController

    @property (weak, nonatomic) IBOutlet UIScrollView *theScroller;

    @property (weak, nonatomic) NSString *startDate;
    @property (weak, nonatomic) NSString *stopDate;

    - (IBAction)exitToReservations:(UIStoryboardSegue *)sender;

@end

FLViewController.m

#import "FLViewController.h"

@interface FLViewController ()

    @property (weak, nonatomic) IBOutlet UIDatePicker *startReservationDatePicker;
    @property (weak, nonatomic) IBOutlet UIDatePicker *stopReservationDatePicker;

@end

@implementation FLViewController

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        [self.theScroller setScrollEnabled:YES];
        [self.theScroller setContentSize:CGSizeMake(280, 1000)];

        //setup reservationDatePicker
        [self.startReservationDatePicker addTarget:self
                                            action:@selector(startDatePickerChanged:)
                                  forControlEvents:UIControlEventValueChanged];
        [self.stopReservationDatePicker addTarget:self
                                           action:@selector(stopDatePickerChanged:)
                                 forControlEvents:UIControlEventValueChanged];

    }

    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }

    // add method called when user changes start date
    - (void)startDatePickerChanged:(UIDatePicker *)datePicker
    {
        NSDateFormatter *dateFortmatter = [[NSDateFormatter alloc] init];
        [dateFortmatter setDateFormat:@"dd--MM-yyyy HH:mm"];
        // get date using stringFromData: method and getter datePicker.date
        self.startDate = [dateFortmatter stringFromDate:datePicker.date];
        NSLog(@"The start date is %@", self.startDate);
    }

    // add method called when user changes stop date
    - (void)stopDatePickerChanged:(UIDatePicker *)datePicker
    {
        NSDateFormatter *dateFortmatter = [[NSDateFormatter alloc] init];
        [dateFortmatter setDateFormat:@"dd--MM-yyyy HH:mm"];
        // get date using stringFromData: method and getter datePicker.date
        self.stopDate= [dateFortmatter stringFromDate:datePicker.date];
        NSLog(@"The stop date is %@", self.stopDate);

    }

    - (IBAction)exitToReservations:(UIStoryboardSegue *)sender {
        // execute this code upon unwinding
            [self dismissViewControllerAnimated:YES completion:nil];
    }

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
        if ([segue.identifier isEqualToString:@"toEmailReservationViewController"]) {
            FLSendEmailViewController *controller = (FLSendEmailViewController         *)segue.destinationViewController;
            if (!controller.startDateField.text) {

                controller.startDateField.text = @"today";
                NSLog(@"in vc startDate is null but set to %@",controller.startDateField.text );
            }
        }
    }
@end

FLSendEmailViewController.h

#import <UIKit/UIKit.h>

@class FLViewController;

    @interface FLSendEmailViewController : UIViewController

    @property (retain, nonatomic) IBOutlet UITextField *startDateField;
    @property (retain, nonatomic) IBOutlet UITextField *stopDateField;

@end

FLSendEmailViewController.m

#import "FLSendEmailViewController.h"
#import "FLViewController.h"

@interface FLSendEmailViewController ()

    - (IBAction)sendEmail:(id)sender;

    @property (weak, nonatomic) IBOutlet UITextField *numberOfDoggies;
    @property (weak, nonatomic) IBOutlet UITextField *emailAddressField;

    - (IBAction)hideKeyboard:(id)sender;

@end

@implementation FLSendEmailViewController

    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
        // Custom initialization
        }
        return self;
    }

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.startDateField.text = ((FLViewController *)self.presentingViewController).startDate;

    }

    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }

    - (IBAction)sendEmail:(id)sender {
        NSString *emailString = [NSString stringWithFormat:@"I would like you to watch my %@ doggies from %@ to %@.  Thank you.", self.numberOfDoggies.text, self.startDateField.text, self.stopDateField.text];
        NSLog(@"%@",emailString);
    }
    - (IBAction)hideKeyboard:(id)sender {

        [self.startDateField resignFirstResponder];
    }
@end

Solution

    1. Import the FLSendEmailViewController.h to the "InitialViewController.h"

    2. Add this property to the FLSendEmailViewController.h

      @property (nonatomic, strong) NSString *exportedData;

    3. Add this to the FLSendEmailViewController.m

      - (void)viewDidLoad
      {
          [super viewDidLoad];
          self.startDateField.text = self.exportedData
      }
      

    4.

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
     {
    if ([segue.identifier isEqualToString:@"toEmailReservationViewController"]) {
        FLSendEmailViewController *controller = (FLSendEmailViewController     *)segue.destinationViewController;
        if (!controller.startDateField.text) {
    
            controller.exportedData = @"today";
        }
    
    }
    }