Search code examples
iosios7ios8

iOS8: Not show UIPopoverController but iOS7 is OK


Apple seems to change the attitude of UIPopoverController since iOS8.

Please look at the code below. I want to show UIPopoverController after addSubview. iOS6 and iOS7 are no problem but it does not display on iOS8.

Could you suggest any possible reasons? Any help will be appreciated it.

- (IBAction)tapButton:(id)sender {

    SampleView *sampleView = [[SampleView alloc] initWithFrame:CGRectMake(0.0f, 0.0f,
                                                                          [UIScreen mainScreen].bounds.size.width,
                                                                          [UIScreen mainScreen].bounds.size.height)];
    sampleView.backgroundColor = [UIColor blueColor];
    sampleView.alpha = 0.5;

    sampleView.label = [[UILabel alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width / 2,
                                                                 [UIScreen mainScreen].bounds.size.height / 2,
                                                                 200.0f, 20.0f)];
    sampleView.label.text = @"SAMPLE TEXT";
    sampleView.label.textColor = [UIColor redColor];
    [sampleView addSubview:sampleView.label];

    [self.view.window addSubview:sampleView];

    if (!self.popover) {
        UIViewController *vc = [[UIViewController alloc] init];
        vc.view.backgroundColor = [UIColor redColor];
        vc.preferredContentSize = CGSizeMake(200, 300);
        self.popover = [[UIPopoverController alloc] initWithContentViewController:vc];
    }

    // On iOS7 is OK but not show on iOS8
    [self.popover presentPopoverFromRect:CGRectMake(200, 100, 0, 0)
                                  inView:sampleView.label
                permittedArrowDirections:UIPopoverArrowDirectionUp
                                animated:YES];
}

enter image description here

enter image description here

Update1:

I followed by this question's answer.

in iOS8: UIPopoverController presentPopoverFromRect not work for keyWindow any more

This is updated code.

[self.popover presentPopoverFromRect:CGRectMake(200, 100, 0, 0)
                                  inView:self.view
                permittedArrowDirections:UIPopoverArrowDirectionUp
                                animated:YES];

enter image description here

As far as I checked, keyWindos and self.view.window seems to be same.

NSLog(@"%@", [UIApplication sharedApplication].keyWindow);
NSLog(@"%@", self.view.window);

However, this is not complete solution for my case. I want to control views on the added subview.

Update2:

I guess that I need to use UIPopoverPresentationController on iOS8.

- (IBAction)tapButton:(id)sender {

    // View
    SampleView *sampleView = [[SampleView alloc] initWithFrame:CGRectMake(0.0f, 0.0f,
                                                                          [UIScreen mainScreen].bounds.size.width,
                                                                          [UIScreen mainScreen].bounds.size.height)];
    sampleView.backgroundColor = [UIColor blueColor];
    sampleView.alpha = 0.5;

    // Label
    sampleView.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 20.0f)];
    sampleView.label.text = @"SAMPLE TEXT";
    sampleView.label.textColor = [UIColor redColor];
    [sampleView addSubview:sampleView.label];

    // View Controller
    UIViewController *viewController = [[UIViewController alloc] init];
    viewController.modalPresentationStyle = UIModalPresentationPopover;
    viewController.view = sampleView;

    // UIPopoverPresentationController
    UIPopoverPresentationController *presentationController = viewController.popoverPresentationController;
    [presentationController setDelegate:self];
    presentationController.permittedArrowDirections = 0;
    presentationController.sourceView = [[UIApplication sharedApplication] keyWindow];
    presentationController.sourceRect = [[UIApplication sharedApplication] keyWindow].bounds;

    [viewController setPreferredContentSize:CGSizeMake(320, 480)];
    [self presentViewController:viewController animated:YES completion:nil];

    if (!self.popover) {
        UIViewController *vc = [[UIViewController alloc] init];
        vc.view.backgroundColor = [UIColor redColor];
        vc.preferredContentSize = CGSizeMake(200, 300);
        vc.modalPresentationStyle = UIModalPresentationPopover;
        self.popover = [[UIPopoverController alloc] initWithContentViewController:vc];
        self.popover.delegate = self;
    }

    [self.popover presentPopoverFromRect:CGRectMake(300, 300, 0, 0)
                                  inView:viewController.view
                permittedArrowDirections:UIPopoverArrowDirectionUp
                                animated:YES];
}

enter image description here

Update3 I used dispatch_async but not worked. Some say that dispatch_async is effective in this case. dispatch_async is very simple solution. I prefer to use it. If you can fix my problem by using dispatch_async, I would be grateful you could attache the code.

- (IBAction)tapButton:(id)sender {

    SampleView *sampleView = [[SampleView alloc] initWithFrame:CGRectMake(0.0f, 0.0f,
                                                                          [UIScreen mainScreen].bounds.size.width,
                                                                          [UIScreen mainScreen].bounds.size.height)];
    sampleView.backgroundColor = [UIColor blueColor];
    sampleView.alpha = 0.5;

    sampleView.label = [[UILabel alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width / 2,
                                                                 [UIScreen mainScreen].bounds.size.height / 2,
                                                                 200.0f, 20.0f)];
    sampleView.label.text = @"SAMPLE TEXT";
    sampleView.label.textColor = [UIColor redColor];
    [sampleView addSubview:sampleView.label];

    [self.view.window addSubview:sampleView];

    if (!self.popover) {
        UIViewController *vc = [[UIViewController alloc] init];
        vc.view.backgroundColor = [UIColor redColor];
        vc.preferredContentSize = CGSizeMake(200, 300);
        self.popover = [[UIPopoverController alloc] initWithContentViewController:vc];
    }

    // I tried this but not worked.
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.popover presentPopoverFromRect:CGRectMake(200, 100, 0, 0)
                                      inView:sampleView.label
                    permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
    });
}

Solution

  • Try and do the following for iOS 8

       dispatch_async( dispatch_get_main_queue(), ^{
        [self.popover presentPopoverFromRect:CGRectMake(200, 100, 0, 0) inView:sampleView.label permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
    });
    

    EDIT

    This is my code, it works With or without dispatch_async.

     self.popover = [[UIPopoverController alloc] initWithContentViewController:[self.storyboard instantiateViewControllerWithIdentifier:@"second"]];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.popover presentPopoverFromRect:self.button.frame inView:self.button permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
        });