1

In a ViewController I have the following:

- (void)viewWillAppear:(BOOL)animated
{
    DataObject *theDataObject = [self theAppDataObject];
    NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
    [formatter setDateFormat:@"MMM dd, yyyy HH:mm"];
    NSString *dateStr = [formatter stringFromDate:theDataObject.deadline];
    NSLog(@"Logged dateStr: %@", dateStr);
    [dateTimeLabel setText:dateStr];
    [super viewWillAppear:animated];
}

To clarify: dateTimeLabel IS wired up in the xib file. The viewWillAppear method is explicitly called from another ViewController, and is firing, like so:

- (IBAction)setDateTimeButtonClicked:(id)sender
{
    DataObject *theDataObject = [self theAppDataObject];

    theDataObject.deadline = [datePicker date];

    FirstMobileViewController *mobileVC = [[FirstMobileViewController alloc] init];
    [mobileVC viewWillAppear:YES];
    [mobileVC release];

    [UIView transitionWithView:self.view.superview 
                      duration:0.5 
                       options:UIViewAnimationOptionTransitionFlipFromRight | UIViewAnimationOptionLayoutSubviews | UIViewAnimationOptionAllowAnimatedContent 
                    animations:^{[self.view removeFromSuperview];} 
                    completion:NULL];
}

The viewWillAppear method is firing -- the dateStr is logged by NSLog appropriately when the superview is shown again. But the dateTimeLabel never updates. Obviously, commenting the NSLog line doesn't make a difference.

The MADDENING thing is that even though NSLog logs dateStr just fine, if I change dateStr to, say, @"Yo!" or even to a locally initialized string, then dateTimeLabel will update, no problem.

What am I missing here?

Lockjaw
  • 1,882
  • 2
  • 16
  • 15
  • Are you sure that `[super viewWillAppear:animated];` needs to be called at the end, not at the beginning of your implementation? Try moving the call to the first line of the implementation and see if it makes a difference. – Sergey Kalinichenko Mar 09 '12 at 04:22
  • @dasblinkenlight I tried moving the `super` call to the top and it didn't make a difference. Really, it felt like a shot in the dark, because a string literal works just fine: `[dateTimeLabel setText:@"Woof!"]` – Lockjaw Mar 09 '12 at 04:27
  • I guess you must have missed IBOutlet Binding for dateTimeLabel. Check connection for it ? – Janak Nirmal Mar 09 '12 at 04:31
  • @NoMoreWishes Nope -- that's the thing. The `dateTimeLabel` is all wired up. And again, using a string literal works just fine: If I do this, `[dateTimeLabel setText:@"Woof!"]`, then I see `Woof!` as expected. – Lockjaw Mar 09 '12 at 04:40
  • Which version of iOS you are using - iOS 4 or iOS 5 ? – Mrunal Mar 09 '12 at 04:59
  • @mrunal iOS SDK 5.0 is the target. – Lockjaw Mar 09 '12 at 05:23
  • In iOS 5 all this view life cycle methods gets called properly but in iOS 4 it is not. Check this: http://stackoverflow.com/questions/8089287/in-ios-4-x-or-lower-viewdidappear-method-is-not-getting-called-while-adding-sub – Mrunal Mar 09 '12 at 05:29
  • @mrunal Great heads-up and good info overall -- thank you! But iOS 5 is the target and `viewWillAppear` is being called explicitly. – Lockjaw Mar 09 '12 at 05:34
  • @Lockjaw: Try to put [super viewWillAppear:animated]; as first line in that method. I am not sure about this whether it will help you or not. But as per coding rule it should load super first. – Mrunal Mar 09 '12 at 05:42
  • @mrunal Thanks -- no dice. See above. – Lockjaw Mar 09 '12 at 06:01
  • viewWillAppear isn't supposed to be called directly. It's called internally when your view controller's view is about to appear. You need to present the view controller properly, as stated in a couple of the answers. – jrturton Mar 09 '12 at 07:00

3 Answers3

3

You method to add a child view controller isn't correct. Try with the following code (with your method, when you call ViewWillAppear, think that the view of the view controller isn't yet initialized. (you san check that with a simple hack: adding mobileVC.view; just after the mobileVC initialization)

    - (IBAction)setDateTimeButtonClicked:(id)sender {
        DataObject *theDataObject = [self theAppDataObject];

        theDataObject.deadline = [datePicker date];

        FirstMobileViewController *mobileVC = [[FirstMobileViewController alloc] init];
        [self addChildViewController:mobileVC];
        UIView *superView = self.view.superview;
        mobileVC.view.frame = superView.bounds;

        [UIView transitionWithView:superview 
                          duration:0.5 
                           options:UIViewAnimationOptionTransitionFlipFromRight | UIViewAnimationOptionLayoutSubviews | UIViewAnimationOptionAllowAnimatedContent 
                        animations:^{[self.view removeFromSuperview];
                                      [superview addSubView:mobileVC.view]} 
                        completion:^(BOOL finished) {
                                      [mobileVC didMoveToParentViewController:self];
         }]; 
     }

With this method, the viewWillAppear should be called automatically.

Julien
  • 963
  • 5
  • 8
  • Note that the asker's code was using `release` implying he's in a non-ARC environment. Should either release `mobileVC` at the end of the method, or use the `alloc/init/autorelease` pattern at creation time. – ikuramedia Mar 13 '12 at 09:26
0

Firstly, you're releasing mobileVC before doing anything with it, so while it runs the code in the viewWillAppear: method, that's all that happens.

You're also not loading the XIB file for mobileVC, since you only alloc and init it. Therefore the objects you reference within viewWillAppear most likely don't exist at the point that you explicitly call the method.

You haven't shown the code that you use to present the mobileVC so it's hard to guess what the fix will be, or to understand the quirky problem you're having with string literals working. But, suffice to say, when you present the new view controller, it will be a different instance than the one you explicitly called.

Possible fix:

  1. Use initWithNibName:bundle: instead of plain init to ensure that your XIB is loaded. Then pass mobileVC into the completion block of your transition to present it?
ikuramedia
  • 6,038
  • 3
  • 28
  • 31
0

Put [super viewWillAppear:animated] at the beginning of viewWillAppear.

Maybe you never connect dateTimeLabel in xib to dateTimeLabel.

Try to use [self. dateTimeLabel setText: dateStr]

Wu Huajie
  • 1
  • 1