检测 SKStoreReviewController 是否在 macOS 上显示应用评级 window
Detect if SKStoreReviewController has displayed app rating window on macOS
审稿方式
SKStoreReviewController.requestReview()
在 iOS 上,人们找到了一种非常简单的方法来查找评分 window 是否已呈现 link(只需计算应用程序中 windows 的数量)
如何在 macOS 上可靠地检测到这个? (计算 windows 个备选方案?)
发现 CGWindowListCopyWindowInfo
+ NSRunningApplication 是正确的检查对象:
dispatch_time_t twoSecondsFromNow = DISPATCH_TIME_NOW + 2.0;
dispatch_after(twoSecondsFromNow, dispatch_get_main_queue(), ^{
//HERE REQUEST REVIEW
[SKStoreReviewController requestReview];
dispatch_time_t secondFromNow = DISPATCH_TIME_NOW + 1.0;
dispatch_after(secondFromNow, dispatch_get_main_queue(), ^{
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSArray <NSString*>*windowNames = [(__bridge NSArray *)windowList valueForKey:@"kCGWindowOwnerName"];
CFRelease(windowList);
if ([windowNames containsObject:@"storeuid"]) {
//REPORT TO PREFERENCES THAT WE SUCCESSFULLY ASKED FOR REVIEW
NSLog(@"Rating Window was presented");
}
});
});
可能的替代方案(自 10.14.2 起停用有明显延迟):
- (void)findRunningApplication
{
NSArray<NSRunningApplication *> *runningApplications = [[NSWorkspace sharedWorkspace] runningApplications];
for (NSRunningApplication *app in runningApplications) {
if ([[app bundleIdentifier] isEqualToString:@"com.apple.storeuid"]) {
[self setRunningApplication:app];
}
}
}
- (void)setRunningApplication:(NSRunningApplication *)runningApplication
{
if (runningApplication != _runningApplication) {
if (runningApplication == nil) {
[_runningApplication removeObserver:self forKeyPath:@"active"];
} else {
[runningApplication addObserver:self forKeyPath:@"active" options:NSKeyValueObservingOptionNew context:StoreInspectorKVOContext];
}
_runningApplication = runningApplication;
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
if (context == StoreInspectorKVOContext) {
if (object == [self runningApplication] && [keyPath isEqualToString:@"active"]) {
[self runningApplicationActiveHasChanged];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
甚至可以通过 cgwindow 的全局监控事件 + 位置获取用户点击的评分
NSEvent *monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:(NSEventMaskLeftMouseDown)
handler:^(NSEvent *event) {
NSLog(@"%@",event);
}];
2019-01-13 23:58:12.727979+0100 testWindows2[11466:620853] NSEvent: type=LMouseDown loc=(994.746,172.551) time=103867.3 flags=0 win=0x0 winNum=4852 ctxt=0x0 evNum=9320 click=1 buttonNumber=0 pressure=1 deviceID:0x300000014400000 subtype=NSEventSubtypeTouch
2019-01-13 23:58:12.729521+0100 testWindows2[11466:620853] {
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 157;
Width = 420;
X = 786;
Y = 23;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 1248;
kCGWindowNumber = 4590;
kCGWindowOwnerName = storeuid;
kCGWindowOwnerPID = 7017;
kCGWindowSharingState = 1;
kCGWindowStoreType = 1;
}
审稿方式
SKStoreReviewController.requestReview()
在 iOS 上,人们找到了一种非常简单的方法来查找评分 window 是否已呈现 link(只需计算应用程序中 windows 的数量)
如何在 macOS 上可靠地检测到这个? (计算 windows 个备选方案?)
发现 CGWindowListCopyWindowInfo
+ NSRunningApplication 是正确的检查对象:
dispatch_time_t twoSecondsFromNow = DISPATCH_TIME_NOW + 2.0;
dispatch_after(twoSecondsFromNow, dispatch_get_main_queue(), ^{
//HERE REQUEST REVIEW
[SKStoreReviewController requestReview];
dispatch_time_t secondFromNow = DISPATCH_TIME_NOW + 1.0;
dispatch_after(secondFromNow, dispatch_get_main_queue(), ^{
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSArray <NSString*>*windowNames = [(__bridge NSArray *)windowList valueForKey:@"kCGWindowOwnerName"];
CFRelease(windowList);
if ([windowNames containsObject:@"storeuid"]) {
//REPORT TO PREFERENCES THAT WE SUCCESSFULLY ASKED FOR REVIEW
NSLog(@"Rating Window was presented");
}
});
});
可能的替代方案(自 10.14.2 起停用有明显延迟):
- (void)findRunningApplication
{
NSArray<NSRunningApplication *> *runningApplications = [[NSWorkspace sharedWorkspace] runningApplications];
for (NSRunningApplication *app in runningApplications) {
if ([[app bundleIdentifier] isEqualToString:@"com.apple.storeuid"]) {
[self setRunningApplication:app];
}
}
}
- (void)setRunningApplication:(NSRunningApplication *)runningApplication
{
if (runningApplication != _runningApplication) {
if (runningApplication == nil) {
[_runningApplication removeObserver:self forKeyPath:@"active"];
} else {
[runningApplication addObserver:self forKeyPath:@"active" options:NSKeyValueObservingOptionNew context:StoreInspectorKVOContext];
}
_runningApplication = runningApplication;
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
if (context == StoreInspectorKVOContext) {
if (object == [self runningApplication] && [keyPath isEqualToString:@"active"]) {
[self runningApplicationActiveHasChanged];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
甚至可以通过 cgwindow 的全局监控事件 + 位置获取用户点击的评分
NSEvent *monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:(NSEventMaskLeftMouseDown)
handler:^(NSEvent *event) {
NSLog(@"%@",event);
}];
2019-01-13 23:58:12.727979+0100 testWindows2[11466:620853] NSEvent: type=LMouseDown loc=(994.746,172.551) time=103867.3 flags=0 win=0x0 winNum=4852 ctxt=0x0 evNum=9320 click=1 buttonNumber=0 pressure=1 deviceID:0x300000014400000 subtype=NSEventSubtypeTouch
2019-01-13 23:58:12.729521+0100 testWindows2[11466:620853] {
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 157;
Width = 420;
X = 786;
Y = 23;
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 1248;
kCGWindowNumber = 4590;
kCGWindowOwnerName = storeuid;
kCGWindowOwnerPID = 7017;
kCGWindowSharingState = 1;
kCGWindowStoreType = 1;
}