Skip to content

Commit 7c171b3

Browse files
committed
supporting lifecycle observer in unit tests
1 parent d0010ab commit 7c171b3

File tree

9 files changed

+213
-32
lines changed

9 files changed

+213
-32
lines changed

iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,8 @@
424424
DE16C14424D3724700670EFA /* OneSignalLifecycleObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = DE16C14324D3724700670EFA /* OneSignalLifecycleObserver.m */; };
425425
DE16C14524D3724700670EFA /* OneSignalLifecycleObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = DE16C14324D3724700670EFA /* OneSignalLifecycleObserver.m */; };
426426
DE16C14724D3727200670EFA /* OneSignalLifecycleObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = DE16C14624D3727200670EFA /* OneSignalLifecycleObserver.h */; };
427+
DE16C17024D3989A00670EFA /* OneSignalLifecycleObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = DE16C14324D3724700670EFA /* OneSignalLifecycleObserver.m */; };
428+
DE5EFECA24D8DBF70032632D /* OSInAppMessageViewControllerOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = DE5EFEC924D8DBF70032632D /* OSInAppMessageViewControllerOverrider.m */; };
427429
/* End PBXBuildFile section */
428430

429431
/* Begin PBXCopyFilesBuildPhase section */
@@ -698,6 +700,8 @@
698700
CACBAAAB218A662B000ACAA5 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
699701
DE16C14324D3724700670EFA /* OneSignalLifecycleObserver.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OneSignalLifecycleObserver.m; sourceTree = "<group>"; };
700702
DE16C14624D3727200670EFA /* OneSignalLifecycleObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneSignalLifecycleObserver.h; sourceTree = "<group>"; };
703+
DE5EFEC924D8DBF70032632D /* OSInAppMessageViewControllerOverrider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OSInAppMessageViewControllerOverrider.m; sourceTree = "<group>"; };
704+
DE5EFECB24D8DC0E0032632D /* OSInAppMessageViewControllerOverrider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSInAppMessageViewControllerOverrider.h; sourceTree = "<group>"; };
701705
/* End PBXFileReference section */
702706

703707
/* Begin PBXFrameworksBuildPhase section */
@@ -836,6 +840,8 @@
836840
CAAE0DFC2195216900A57402 /* OneSignalOverrider.m */,
837841
9D348538233D2DCF00EB81C9 /* OneSignalLocationOverrider.h */,
838842
9D348539233D2E3600EB81C9 /* OneSignalLocationOverrider.m */,
843+
DE5EFECB24D8DC0E0032632D /* OSInAppMessageViewControllerOverrider.h */,
844+
DE5EFEC924D8DBF70032632D /* OSInAppMessageViewControllerOverrider.m */,
839845
);
840846
path = Shadows;
841847
sourceTree = "<group>";
@@ -1732,6 +1738,7 @@
17321738
CAABF34D205B157B0042F8E5 /* OneSignalExtensionBadgeHandler.m in Sources */,
17331739
912412301E73342200E41FD7 /* OneSignalSelectorHelpers.m in Sources */,
17341740
91F58D851E7C88230017D24D /* OneSignalNotificationSettingsIOS10.m in Sources */,
1741+
DE16C17024D3989A00670EFA /* OneSignalLifecycleObserver.m in Sources */,
17351742
CAAE0DFD2195216900A57402 /* OneSignalOverrider.m in Sources */,
17361743
912412241E73342200E41FD7 /* OneSignalLocation.m in Sources */,
17371744
CA8E190B2194FE0B009DA223 /* OSMessagingControllerOverrider.m in Sources */,
@@ -1806,6 +1813,7 @@
18061813
7AFE856D2368DDB80091D6A5 /* OSFocusCallParams.m in Sources */,
18071814
CA8E19082193C76D009DA223 /* OSInAppMessagingHelpers.m in Sources */,
18081815
4529DEE11FA82AB300CEAB1D /* NSBundleOverrider.m in Sources */,
1816+
DE5EFECA24D8DBF70032632D /* OSInAppMessageViewControllerOverrider.m in Sources */,
18091817
7AF986602447C13C00C36EAE /* OSInfluenceDataRepository.m in Sources */,
18101818
912412441E73342200E41FD7 /* UNUserNotificationCenter+OneSignal.m in Sources */,
18111819
03866CC12378A67B0009C1D8 /* RestClientAsserts.m in Sources */,
Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,32 @@
1-
//
2-
// OneSignalLifecycleObserver.h
3-
// OneSignal
4-
//
5-
// Created by Elliot Mawby on 7/30/20.
6-
// Copyright © 2020 Hiptic. All rights reserved.
7-
//
1+
/**
2+
Modified MIT License
83
9-
@interface OneSignalLifecycleObserver: NSObject
4+
Copyright 2020 OneSignal
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
1. The above copyright notice and this permission notice shall be included in
14+
all copies or substantial portions of the Software.
1015
16+
2. All copies of substantial portions of the Software may only be used in connection
17+
with services provided by OneSignal.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
*/
27+
@interface OneSignalLifecycleObserver: NSObject
1128
+ (OneSignalLifecycleObserver*) sharedInstance;
1229
+ (void)registerLifecycleObserver;
1330
+ (void)removeObserver;
31+
+ (BOOL)isAppUsingUIScene;
1432
@end

iOS_SDK/OneSignalSDK/Source/OneSignalLifecycleObserver.m

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,29 @@
1-
//
2-
// OneSignalLifecycleObserver.m
3-
// OneSignal
4-
//
5-
// Created by Elliot Mawby on 7/30/20.
6-
// Copyright © 2020 Hiptic. All rights reserved.
7-
//
1+
/**
2+
Modified MIT License
3+
4+
Copyright 2020 OneSignal
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
1. The above copyright notice and this permission notice shall be included in
14+
all copies or substantial portions of the Software.
15+
16+
2. All copies of substantial portions of the Software may only be used in connection
17+
with services provided by OneSignal.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
*/
827

928
#import <Foundation/Foundation.h>
1029
#import "OneSignalLifecycleObserver.h"
@@ -28,18 +47,32 @@ +(OneSignalLifecycleObserver*) sharedInstance {
2847
return _instance;
2948
}
3049

50+
+ (BOOL)isAppUsingUIScene {
51+
if (@available(iOS 13.0, *)) {
52+
return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIApplicationSceneManifest"] != nil;
53+
}
54+
return NO;
55+
}
56+
3157
+ (void)registerLifecycleObserver {
3258
// Replacing swizzled lifecycle selectors with notification center observers for scene based Apps
59+
if ([self isAppUsingUIScene]) {
60+
[self registerLifecycleObserverAsUIScene];
61+
} else {
62+
[self registerLifecycleObserverAsUIApplication];
63+
}
64+
}
65+
66+
+ (void)registerLifecycleObserverAsUIScene {
3367
if (@available(iOS 13.0, *)) {
34-
NSDictionary *sceneManifest = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIApplicationSceneManifest"];
3568
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"registering for Scene Lifecycle notifications"];
36-
if (sceneManifest) {
37-
[[NSNotificationCenter defaultCenter] addObserver:[OneSignalLifecycleObserver sharedInstance] selector:@selector(didEnterBackground) name:UISceneDidEnterBackgroundNotification object:nil];
38-
[[NSNotificationCenter defaultCenter] addObserver:[OneSignalLifecycleObserver sharedInstance] selector:@selector(didBecomeActive) name:UISceneDidActivateNotification object:nil];
39-
[[NSNotificationCenter defaultCenter] addObserver:[OneSignalLifecycleObserver sharedInstance] selector:@selector(willResignActive) name:UISceneWillDeactivateNotification object:nil];
40-
return;
41-
}
69+
[[NSNotificationCenter defaultCenter] addObserver:[OneSignalLifecycleObserver sharedInstance] selector:@selector(didEnterBackground) name:UISceneDidEnterBackgroundNotification object:nil];
70+
[[NSNotificationCenter defaultCenter] addObserver:[OneSignalLifecycleObserver sharedInstance] selector:@selector(didBecomeActive) name:UISceneDidActivateNotification object:nil];
71+
[[NSNotificationCenter defaultCenter] addObserver:[OneSignalLifecycleObserver sharedInstance] selector:@selector(willResignActive) name:UISceneWillDeactivateNotification object:nil];
4272
}
73+
}
74+
75+
+ (void)registerLifecycleObserverAsUIApplication {
4376
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"registering for Application Lifecycle notifications"];
4477
[[NSNotificationCenter defaultCenter] addObserver:[OneSignalLifecycleObserver sharedInstance] selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
4578
[[NSNotificationCenter defaultCenter] addObserver:[OneSignalLifecycleObserver sharedInstance] selector:@selector(didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];

iOS_SDK/OneSignalSDK/Source/OneSignalNotificationServiceExtensionHandler.m

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,8 @@ @implementation OneSignalNotificationServiceExtensionHandler
4040

4141
+ (UNMutableNotificationContent*)didReceiveNotificationExtensionRequest:(UNNotificationRequest*)request
4242
withMutableNotificationContent:(UNMutableNotificationContent*)replacementContent {
43-
// Set default log level of NSE to VERBOSE so we get all logs from NSE logic
44-
[OneSignal setLogLevel:ONE_S_LL_VERBOSE visualLevel:ONE_S_LL_NONE];
45-
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"NSE request received, setting OneSignal log level to VERBOSE!"];
43+
44+
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"NSE request received"];
4645

4746
if (!replacementContent)
4847
replacementContent = [request.content mutableCopy];
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
Modified MIT License
3+
4+
Copyright 2020 OneSignal
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
1. The above copyright notice and this permission notice shall be included in
14+
all copies or substantial portions of the Software.
15+
16+
2. All copies of substantial portions of the Software may only be used in connection
17+
with services provided by OneSignal.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
*/
27+
28+
@interface OSInAppMessageViewControllerOverrider : NSObject
29+
30+
@end
31+
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Modified MIT License
3+
*
4+
* Copyright 2020 OneSignal
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* 1. The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* 2. All copies of substantial portions of the Software may only be used in connection
17+
* with services provided by OneSignal.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#import <Foundation/Foundation.h>
29+
#import "OSInAppMessageViewControllerOverrider.h"
30+
#import "OSInAppMessageViewController.h"
31+
#import "OneSignalSelectorHelpers.h"
32+
33+
@implementation OSInAppMessageViewControllerOverrider
34+
35+
+ (void)load {
36+
#pragma clang diagnostic push
37+
#pragma clang diagnostic ignored "-Wundeclared-selector"
38+
injectToProperClass(@selector(overrideAnimateAppearance), @selector(animateAppearance), @[], [OSInAppMessageViewControllerOverrider class], [OSInAppMessageViewController class]);
39+
#pragma clang diagnostic pop
40+
}
41+
42+
- (void)overrideAnimateAppearance {
43+
44+
}
45+
46+
@end

iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ NSString * serverUrlWithPath(NSString *path);
4040
+ (void)setCurrentNotificationPermissionAsUnanswered;
4141
+ (void)foregroundApp;
4242
+ (void)backgroundApp;
43+
+ (void)useSceneLifecycle:(BOOL)useSceneLifecycle;
4344
+ (void)initOneSignal;
4445
+ (void)initOneSignalAndThreadWait;
4546
+ (void)runBackgroundThreads;

iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.m

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#import "OneSignalNotificationServiceExtensionHandler.h"
5454
#import "OneSignalTrackFirebaseAnalytics.h"
5555
#import "OSMessagingControllerOverrider.h"
56+
#import "OneSignalLifecycleObserver.h"
5657

5758
NSString * serverUrlWithPath(NSString *path) {
5859
return [OS_API_SERVER_URL stringByAppendingString:path];
@@ -158,6 +159,8 @@ + (void)clearStateForAppRestart:(XCTestCase *)testCase {
158159
[NSTimerOverrider reset];
159160

160161
[OSMessagingController.sharedInstance resetState];
162+
163+
[OneSignalLifecycleObserver removeObserver];
161164
}
162165

163166
+ (void)beforeAllTest:(XCTestCase *)testCase {
@@ -218,14 +221,35 @@ + (void)initOneSignalAndThreadWait {
218221

219222
+ (void)foregroundApp {
220223
UIApplicationOverrider.currentUIApplicationState = UIApplicationStateActive;
221-
UIApplication *sharedApp = [UIApplication sharedApplication];
222-
[sharedApp.delegate applicationDidBecomeActive:sharedApp];
224+
225+
if ([OneSignalLifecycleObserver isAppUsingUIScene]) {
226+
if (@available(iOS 13.0, *)) {
227+
[[NSNotificationCenter defaultCenter] postNotificationName:UISceneDidActivateNotification object:nil];
228+
}
229+
} else {
230+
[[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidBecomeActiveNotification object:nil];
231+
}
223232
}
224233

225234
+ (void)backgroundApp {
226235
UIApplicationOverrider.currentUIApplicationState = UIApplicationStateBackground;
227-
UIApplication *sharedApp = [UIApplication sharedApplication];
228-
[sharedApp.delegate applicationWillResignActive:sharedApp];
236+
if ([OneSignalLifecycleObserver isAppUsingUIScene]) {
237+
if (@available(iOS 13.0, *)) {
238+
[[NSNotificationCenter defaultCenter] postNotificationName:UISceneWillDeactivateNotification object:nil];
239+
[[NSNotificationCenter defaultCenter] postNotificationName:UISceneDidEnterBackgroundNotification object:nil];
240+
}
241+
} else {
242+
[[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationWillResignActiveNotification object:nil];
243+
[[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidEnterBackgroundNotification object:nil];
244+
}
245+
}
246+
247+
//Call this method before init OneSignal. Make sure not to overwrite the NSBundleDictionary in later calls.
248+
+ (void)useSceneLifecycle:(BOOL)useSceneLifecycle {
249+
NSMutableDictionary *currentBundleDictionary = [[NSMutableDictionary alloc] initWithDictionary:NSBundleOverrider.nsbundleDictionary];
250+
if (useSceneLifecycle)
251+
[currentBundleDictionary setObject:@[@"SceneDelegate"] forKey:@"UIApplicationSceneManifest"];
252+
NSBundleOverrider.nsbundleDictionary = currentBundleDictionary;
229253
}
230254

231255
+ (void)setCurrentNotificationPermission:(BOOL)accepted {

iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,17 @@ - (void)registerForPushNotifications {
142142

143143
- (void)backgroundApp {
144144
UIApplicationOverrider.currentUIApplicationState = UIApplicationStateBackground;
145-
UIApplication *sharedApp = [UIApplication sharedApplication];
146-
[sharedApp.delegate applicationWillResignActive:sharedApp];
145+
if (@available(iOS 13.0, *)) {
146+
NSDictionary *sceneManifest = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIApplicationSceneManifest"];
147+
if (sceneManifest) {
148+
[[NSNotificationCenter defaultCenter] postNotificationName:UISceneWillDeactivateNotification object:nil];
149+
[[NSNotificationCenter defaultCenter] postNotificationName:UISceneDidEnterBackgroundNotification object:nil];
150+
return;
151+
}
152+
}
153+
[[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationWillResignActiveNotification object:nil];
154+
[[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidEnterBackgroundNotification object:nil];
155+
147156
}
148157

149158
- (UNNotificationResponse*)createBasiciOSNotificationResponse {
@@ -1673,13 +1682,25 @@ - (void)testFirstInitWithNotificationsAlreadyDeclined {
16731682
XCTAssertEqual(OneSignalClientOverrider.networkRequestCount, 2);
16741683
}
16751684

1676-
- (void)testPermissionChangedInSettingsOutsideOfApp {
1685+
- (void)testPermissionChangedInSettingsOutsideOfAppWithAppDelegate {
1686+
[self permissionChangedInSettingsOutsideOfApp:NO];
1687+
}
1688+
1689+
- (void)testPermissionChangedInSettingsOutsideOfAppWithSceneDelegate {
1690+
[self permissionChangedInSettingsOutsideOfApp:YES];
1691+
}
1692+
1693+
- (void)permissionChangedInSettingsOutsideOfApp: (BOOL)useSceneDelegate {
1694+
16771695
[UnitTestCommonMethods clearStateForAppRestart:self];
16781696

16791697
[self backgroundModesDisabledInXcode];
16801698
UNUserNotificationCenterOverrider.notifTypesOverride = 0;
16811699
UNUserNotificationCenterOverrider.authorizationStatus = [NSNumber numberWithInteger:UNAuthorizationStatusDenied];
16821700

1701+
1702+
[UnitTestCommonMethods useSceneLifecycle: useSceneDelegate];
1703+
16831704
[UnitTestCommonMethods initOneSignalAndThreadWait];
16841705

16851706
OSPermissionStateTestObserver* observer = [OSPermissionStateTestObserver new];

0 commit comments

Comments
 (0)