문제

I have a view controller which queries a web service as to whether an interstitial ad should be shown. If so, another view controller is instantiated and presented using presentViewController:animated:completion:. According to this answer and the docs, I would assume viewDidAppear: would not be called when dismissing the presented view controller (which it does itself). Conceptually, to me anyway, the presenting view controller's view is never removed from the view hierarchy and therefore never needs to "reappear". I'm obviously wrong. So what is going on? Why is what I'm seeing differing from what the docs say?

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [[AdService sharedAdService] adForSlotName:@"Main Interstitial" completionBlock:^(Ad *adForSlotName) {

        if(adForSlotName)
        {
            InterstitialAdViewController_iPhone *interstitialAdViewController = [[InterstitialAdViewController_iPhone alloc] init];
            interstitialAdViewController.ad = adForSlotName;

            dispatch_queue_t mainQueue = dispatch_get_main_queue();
            dispatch_async(mainQueue, ^{

                [self presentViewController:interstitialAdViewController animated:YES completion:^{}];

            });

            [interstitialAdViewController release];
        }
    }];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [[AdService sharedAdService] clearAdForSlotName:@"Main Interstitial"];

    [super viewWillDisappear:animated];
}
도움이 되었습니까?

해결책

The answer to which you linked is about the behavior of viewDidDisappear, not viewDidAppear. The note in the documentation you linked says that viewDidAppear will not be called on the presenting view controller when a child view controller presented with a popover is dismissed.

In your case you are presenting the child view controller without a popover, so I read the doc's note (in an "exception that proves the rule" way) as saying that viewDidAppear should be called on the presenting view controller when the child view controller is dismissed in your case.

I think you should be seeing viewDidDisappear called on your parent view controller when the child view controller is presented. I tried this out in a minimal test app, using this code to present a child view controller:

Parent *parent = [[Parent alloc] initWithNibName:nil bundle:nil];
[self.window setRootViewController:parent];
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    Child *child = [[Child alloc] initWithNibName:nil bundle:nil];
    [parent presentViewController:child animated:YES completion:^{
        NSLog(@"Child presented");
        double delayInSeconds = 2.0;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [parent dismissViewControllerAnimated:YES completion:^{
                NSLog(@"Child dismissed");
            }];
        });
    }];
});

and, logging the calls to the various appearance related callbacks in both the Parent and Child class. This is the sequence I see:

Making the parent view controller the root view controller:

Parent viewWillAppear:
Parent viewDidAppear:

Presenting the child view controller:

Parent viewWillDisappear:
Child viewWillAppear:
Child viewDidAppear:
Parent viewDidDisappear:
Child presented

Dismissing the child view controller:

Child viewWillDisappear:
Parent viewWillAppear:
Parent viewDidAppear:
Child viewDidDisappear:
Child dismissed

So this seems internally consistent to me---the parent gets the disappearance calls when the child view controller is presented and the appearance calls when the child view controller is dismissed. And this is still consistent with the documented behavior of viewWillAppear because I'm not presenting the child view controller with a popover.

I'm afraid I don't know why you're not getting the viewWill/DidDisappear calls when your child view controller is presented.

다른 팁

I have experienced the same behaviour. The viewDidAppear: method is called when dismissing presented view controller. However, there is a way out. Create a boolean variable inside your controller, set it to NO in viewDidLoad and check it in viewDidAppear:. Then set it to YES. Like so:

#import "MyViewController.h"

@implementation MyViewController {
    BOOL alreadyShown;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    alreadyShown = NO;
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    if (!alreadyShown) {
        alreadyShown = YES;
        //do your stuff
    }
}

@end
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top