IOS 10.3 app rating dialog box display detection mechanism?

TL DR: Is there an iOS way to detect the presence / display of the App Store App App dialog box added in iOS 10.3?

Recently, I added support for my new applications , described here ), namely, that the dialogue may or may not be presented when the above function is called, cases are not considered if the client has already rated the application or the client has reduced it 3 times.

I also know that Apple does not expect that the presentation of the dialog will be directly triggered by the user's action and, therefore, the presence of a dialog box that will be reported:

Although you should call this method when it makes sense in the user experience flow of your application, the actual display of the rating view / view request is governed by the application store policy. Since this method may or may not contain a warning, it is not recommended to call it in response to a button click or other user action.

But this does not stop the UX team from placing these buttons in graphic projects and asking, “can we know if the dialog box was shown”?

So my question is, is there another indirect way to determine the presentation of this dialogue?

Android iOS Appium Xpaths, , , , iOS.

+4
2

, , .

UIWindow - , UIWindow - ! , . :

method : windowDidBecomeVisibleNotification:  
object -> <SKStoreReviewPresentationWindow: 0x7fe14bc03670; baseClass = UIApplicationRotationFollowingWindow; frame = (0 0; 414 736); opaque = NO; gestureRecognizers = <NSArray: 0x61800004de30>; layer = <UIWindowLayer: 0x61800003baa0>>

, , , object, :

- (void)viewDidLoad {
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(windowDidBecomeVisibleNotification:)
                                                 name:UIWindowDidBecomeVisibleNotification
                                               object:nil];
}

- (void)windowDidBecomeVisibleNotification:(NSNotification *)notification {
    if ([notification.object isKindOfClass:NSClassFromString(@"SKStoreReviewPresentationWindow")]) {
        NSLog(@"the review request was shown!");
    }
}

, SKStoreReviewPresentationWindow , [SKStoreReviewPresentationWindow class], NSClassFromString - - . , , UIWindowDidResignKey, - , , , , . , . , , notification.object [UIApplication sharedApplication].window, - UITextEffectsWindow UIRemoteKeyboardWindow, , .

- Apple, . , , . iPhone 7+ Simulator, iOS 10.3, Xcode 8.3.2


, , , , , . -, -, . , , . , , , , Apple .

+9

, :

. Swizzling, . Apple, , , .

SKStoreReviewPresentationWindow UIWindow, UIWindow, , :

@interface MonitorObject:NSObject

@property (nonatomic, weak) UIWindow* owner;

-(id)init:(UIWindow*)owner;
-(void)dealloc;

@end

@interface UIWindow (DismissNotification)

+ (void)load;

@end

#import "UIWindow+DismissNotification.h"
#import <objc/runtime.h>

@implementation MonitorObject


-(id)init:(UIWindow*)owner
{
    self = [super init];
    self.owner = owner;
    [[NSNotificationCenter defaultCenter] postNotificationName:UIWindowDidBecomeVisibleNotification object:self];
    return self;

}
-(void)dealloc
{
      [[NSNotificationCenter defaultCenter] postNotificationName:UIWindowDidBecomeHiddenNotification object:self];
}

@end



@implementation UIWindow (DismissNotification)

static NSString* monitorObjectKey = @"monitorKey";
static NSString* partialDescForStoreReviewWindow =  @"SKStore";
+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];

        SEL originalSelector = @selector(setWindowLevel:);
        SEL swizzledSelector = @selector(setWindowLevel_startMonitor:);

        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        BOOL didAddMethod =
        class_addMethod(class,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));

        if (didAddMethod) {
            class_replaceMethod(class,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}


#pragma mark - Method Swizzling

- (void)setWindowLevel_startMonitor:(int)level{
    [self setWindowLevel_startMonitor:level];

    if([self.description containsString:partialDescForStoreReviewWindow])
    {
        MonitorObject *monObj = [[MonitorObject alloc] init:self];
        objc_setAssociatedObject(self, &monitorObjectKey, monObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    }
}

@end

:

:

 [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(windowDidBecomeVisibleNotification:)
                                                 name:UIWindowDidBecomeVisibleNotification
                                               object:nil];


 [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(windowDidBecomeHiddenNotification:)
                                                 name:UIWindowDidBecomeHiddenNotification
                                               object:nil];

, :

- (void)windowDidBecomeVisibleNotification:(NSNotification *)notification
{
    if([notification.object class] == [MonitorObject class])
    {
        NSLog(@"Review Window shown!");
    }
}

- (void)windowDidBecomeHiddenNotification:(NSNotification *)notification
{
    if([notification.object class] == [MonitorObject class])
    {
        NSLog(@"Review Window hidden!");
    }
}

+1

Source: https://habr.com/ru/post/1676186/


All Articles