Reputation: 109
By dismissing the SKStoreProductViewController
quickly (and it's very intuitive to the user since its presentation style is a page sheet), this view controller is not presenting anymore but it seems that the system UI still "thinks" that SKStoreProductViewController
is still being presented.
Xcode view hierarchy tool shows that SKStoreProductViewController
is still presented on top of the view controllers and productViewControllerDidFinish:
delegate method is not being called.
Is there a proven workaround for this issue?
Upvotes: 3
Views: 683
Reputation: 1
I tried Kegluneq's answer, it's not work for me. It seems break the vc transaction when quick dismiss. My solution is prevent user from quick dismiss when StoreVC presenting, below is my sample code. I test it for many times with quick dismiss, about 99% productViewControllerDidFinish :
will be called. And I hope someone's solution can fix it completely!
#import "ViewController.h"
#import <StoreKit/StoreKit.h>
@interface ViewController () <SKStoreProductViewControllerDelegate, UIViewControllerTransitioningDelegate>
@property (weak, nonatomic) IBOutlet UIButton *actionButton;
@property (nonatomic, strong) UIView *maskView;
@property (nonatomic, strong) CADisplayLink *maskTimer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)showProductVCAction:(id)sender {
[self.actionButton setBackgroundColor:UIColor.redColor];
SKStoreProductViewController *vc = [[SKStoreProductViewController alloc] init];
vc.delegate = self;
[vc loadProductWithParameters:@{SKStoreProductParameterITunesItemIdentifier: @(1459204896)} completionBlock:^(BOOL result, NSError * _Nullable error) { }];
UIView *maskView = [[UIView alloc] initWithFrame:self.view.window.bounds];
self.maskView = maskView;
maskView.userInteractionEnabled = YES;
maskView.backgroundColor = [UIColor colorWithWhite:1 alpha:0.001]; // UIColor.clearColor not work
[UIApplication.sharedApplication.keyWindow addSubview:maskView];
self.maskTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(bringMaskToFront)];
[self.maskTimer addToRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
[self presentViewController:vc animated:true completion:^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[maskView removeFromSuperview];
self.maskView = nil;
[self.maskTimer invalidate];
self.maskTimer = nil;
});
}];
}
- (void)bringMaskToFront {
if (!self.maskView) return;
[UIApplication.sharedApplication.keyWindow bringSubviewToFront:self.maskView];
}
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
NSLog(@"SKStoreProductViewController dismiss callback");
[self.actionButton setBackgroundColor:UIColor.clearColor];
}
@end
Upvotes: 0
Reputation: 796
A bit late but for anyone still having this issue. You can set transitioningDelegate
on your SKStoreProductViewController
. Then implement animationControllerForDismissedController:
returning your delegate. On this delegate implement animateTransition
. This will be called even on quick dismiss so you can place your closing logic there. In normal flow it will be called after productViewControllerDidFinish:
Upvotes: 1