Skip to content

Commit 4e1d615

Browse files
committed
Notification Permission Observer - API update
* Rename observer from `OSPermissionObserver` to `OSNotificationPermissionObserver` * Rename and change the method from `onOSPermissionChanged:(OSPermissionStateChanges)` to `onNotificationPermissionDidChange:(BOOL)` * The `OSObservable` infrastructure works with objects, and even though we use NSNumber to get around this, once we pass an NSNumber to the app developer's method that expects a BOOL, it does not work. * Therefore, make another OSBoolObservable just for booleans, and use `NSInvocation` instead of `performSelector` because the latter only works with objects.
1 parent b9a784c commit 4e1d615

File tree

11 files changed

+103
-23
lines changed

11 files changed

+103
-23
lines changed

iOS_SDK/OneSignalDevApp/OneSignalDevApp/AppDelegate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#import <UIKit/UIKit.h>
3232
#import <OneSignalFramework/OneSignalFramework.h>
3333

34-
@interface AppDelegate : UIResponder <UIApplicationDelegate, OSPermissionObserver, OSInAppMessageLifecycleHandler, OSPushSubscriptionObserver>
34+
@interface AppDelegate : UIResponder <UIApplicationDelegate, OSNotificationPermissionObserver, OSInAppMessageLifecycleHandler, OSPushSubscriptionObserver>
3535

3636
@property (strong, nonatomic) UIWindow *window;
3737

iOS_SDK/OneSignalDevApp/OneSignalDevApp/AppDelegate.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ + (void) setOneSignalAppId:(NSString*)onesignalAppId {
117117
// [OneSignal setAppId:onesignalAppId];
118118
}
119119

120-
- (void)onOSPermissionChanged:(OSPermissionState*)state {
121-
NSLog(@"Dev App onOSPermissionChanged: %@", state);
120+
- (void)onNotificationPermissionDidChange:(BOOL)permission {
121+
NSLog(@"Dev App onNotificationPermissionDidChange: %d", permission);
122122
}
123123

124124
- (void)onOSPushSubscriptionChangedWithStateChanges:(OSPushSubscriptionStateChanges *)stateChanges {

iOS_SDK/OneSignalDevApp/OneSignalDevAppClip/AppDelegate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#import <OneSignalFramework/OneSignalFramework.h>
1111

1212
// TODO: Add subscription observer
13-
@interface AppDelegate : UIResponder <UIApplicationDelegate, OSPermissionObserver>
13+
@interface AppDelegate : UIResponder <UIApplicationDelegate, OSNotificationPermissionObserver>
1414

1515
@property (strong, nonatomic) UIWindow *window;
1616

iOS_SDK/OneSignalDevApp/OneSignalDevAppClip/AppDelegate.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ + (void) setOneSignalAppId:(NSString*)onesignalAppId {
112112
[OneSignal initialize:onesignalAppId withLaunchOptions:nil];
113113
}
114114

115-
- (void) onOSPermissionChanged:(OSPermissionState*)state {
116-
NSLog(@"onOSPermissionChanged: %@", state);
115+
- (void)onNotificationPermissionDidChange:(BOOL)permission {
116+
NSLog(@"onNotificationPermissionDidChange: %d", permission);
117117
}
118118

119119
// TODO: Add push sub observer

iOS_SDK/OneSignalSDK/OneSignalCore/Source/OSObservable.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,13 @@
4040
- (BOOL)notifyChange:(ObjectType)state;
4141
@end
4242

43+
// OSBoolObservable is for BOOL states which OSObservable above does not work with
44+
45+
@interface OSBoolObservable<__covariant ObserverType> : NSObject
46+
- (instancetype _Nonnull)initWithChangeSelector:(SEL)selector;
47+
- (void)addObserver:(ObserverType)observer;
48+
- (void)removeObserver:(ObserverType)observer;
49+
- (BOOL)notifyChange:(BOOL)state;
50+
@end
51+
4352
#endif /* OSObservable_h */

iOS_SDK/OneSignalSDK/OneSignalCore/Source/OSObservable.m

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,76 @@ - (void)callObserver:(id)observer withSelector:(SEL)selector withState:(id)state
9595
#pragma clang diagnostic pop
9696

9797
@end
98+
99+
100+
@implementation OSBoolObservable {
101+
NSHashTable* observers;
102+
SEL changeSelector;
103+
}
104+
105+
- (instancetype _Nonnull)initWithChangeSelector:(SEL)selector {
106+
if (self = [super init]) {
107+
observers = [NSHashTable weakObjectsHashTable];
108+
changeSelector = selector;
109+
}
110+
return self;
111+
}
112+
113+
- (instancetype)init {
114+
if (self = [super init])
115+
observers = [NSHashTable new];
116+
return self;
117+
}
118+
119+
- (void)addObserver:(id)observer {
120+
@synchronized(observers) {
121+
[observers addObject:observer];
122+
}
123+
}
124+
125+
- (void)removeObserver:(id)observer {
126+
@synchronized(observers) {
127+
[observers removeObject:observer];
128+
}
129+
}
130+
131+
#pragma clang diagnostic push
132+
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
133+
134+
- (BOOL)notifyChange:(BOOL)state {
135+
BOOL fired = false;
136+
137+
@synchronized(observers) {
138+
NSArray *obs = [observers copy];
139+
for (id observer in obs) {
140+
fired = true;
141+
if (changeSelector) {
142+
// Any Observable setup to fire a custom selector with changeSelector
143+
// is external to our SDK. Run on the main thread in case the
144+
// app developer needs to update UI elements.
145+
146+
[self callObserver:observer withSelector:changeSelector withState:state];
147+
}
148+
}
149+
}
150+
151+
return fired;
152+
}
153+
154+
- (void)callObserver:(id)observer withSelector:(SEL)selector withState:(BOOL)state {
155+
[OneSignalCoreHelper dispatch_async_on_main_queue:^{
156+
// The following declaration is to resolve: Sending 'const BOOL *' (aka 'const bool *') to parameter of type 'void * _Nonnull' discards qualifiers
157+
BOOL boolValue = state;
158+
159+
NSMethodSignature* signature = [[observer class] instanceMethodSignatureForSelector:self->changeSelector];
160+
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
161+
[invocation setTarget: observer];
162+
[invocation setSelector:self->changeSelector];
163+
[invocation setArgument: &boolValue atIndex: 2];
164+
[invocation invoke];
165+
}];
166+
}
167+
168+
#pragma clang diagnostic pop
169+
170+
@end

iOS_SDK/OneSignalSDK/OneSignalNotifications/OSNotificationsManager.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ typedef void (^OSNotificationOpenedBlock)(OSNotificationOpenedResult * _Nonnull
4747
+ (void)requestPermission:(OSUserResponseBlock _Nullable )block;
4848
+ (void)requestPermission:(OSUserResponseBlock _Nullable )block fallbackToSettings:(BOOL)fallback;
4949
+ (void)registerForProvisionalAuthorization:(OSUserResponseBlock _Nullable )block NS_REFINED_FOR_SWIFT;
50-
+ (void)addPermissionObserver:(NSObject<OSPermissionObserver>*_Nonnull)observer NS_REFINED_FOR_SWIFT;
51-
+ (void)removePermissionObserver:(NSObject<OSPermissionObserver>*_Nonnull)observer NS_REFINED_FOR_SWIFT;
50+
+ (void)addPermissionObserver:(NSObject<OSNotificationPermissionObserver>*_Nonnull)observer NS_REFINED_FOR_SWIFT;
51+
+ (void)removePermissionObserver:(NSObject<OSNotificationPermissionObserver>*_Nonnull)observer NS_REFINED_FOR_SWIFT;
5252
+ (void)clearAll;
5353
@end
5454

iOS_SDK/OneSignalSDK/OneSignalNotifications/OSNotificationsManager.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ + (OneSignalNotificationSettings *)osNotificationSettings {
147147
static ObservablePermissionStateChangesType* _permissionStateChangesObserver;
148148
+ (ObservablePermissionStateChangesType*)permissionStateChangesObserver {
149149
if (!_permissionStateChangesObserver)
150-
_permissionStateChangesObserver = [[OSObservable alloc] initWithChangeSelector:@selector(onOSPermissionChanged:)];
150+
_permissionStateChangesObserver = [[OSBoolObservable alloc] initWithChangeSelector:@selector(onNotificationPermissionDidChange:)];
151151
return _permissionStateChangesObserver;
152152
}
153153

@@ -425,15 +425,15 @@ + (void)setSubscriptionErrorStatus:(int)errorType {
425425
[self sendNotificationTypesUpdateToDelegate];
426426
}
427427

428-
// onOSPermissionChanged should only fire if the reachable property changed.
429-
+ (void)addPermissionObserver:(NSObject<OSPermissionObserver>*)observer {
428+
// onNotificationPermissionDidChange should only fire if the reachable property changed.
429+
+ (void)addPermissionObserver:(NSObject<OSNotificationPermissionObserver>*)observer {
430430
[self.permissionStateChangesObserver addObserver:observer];
431431

432432
if (self.currentPermissionState.reachable != self.lastPermissionState.reachable)
433433
[OSPermissionChangedInternalObserver fireChangesObserver:self.currentPermissionState];
434434
}
435435

436-
+ (void)removePermissionObserver:(NSObject<OSPermissionObserver>*)observer {
436+
+ (void)removePermissionObserver:(NSObject<OSNotificationPermissionObserver>*)observer {
437437
[self.permissionStateChangesObserver removeObserver:observer];
438438
}
439439

iOS_SDK/OneSignalSDK/OneSignalNotifications/OSPermission.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ typedef NS_ENUM(NSInteger, OSNotificationPermission) {
4747
};
4848

4949
// Permission Classes
50+
51+
// TODO: this object can be REMOVED now that permission is a boolean
5052
@interface OSPermissionState : NSObject
51-
// TODO: Decide: remove/change properties after addition of canRequestPermission and permission boolean
5253
@property (readonly, nonatomic) BOOL permission;
5354
- (NSDictionary * _Nonnull)jsonRepresentation;
5455
- (instancetype _Nonnull )initWithPermission:(BOOL)permission;
@@ -87,11 +88,11 @@ typedef OSObservable<NSObject<OSPermissionStateObserver>*, OSPermissionState*> O
8788
- (NSDictionary * _Nonnull)jsonRepresentation;
8889
@end
8990

90-
@protocol OSPermissionObserver <NSObject>
91-
- (void)onOSPermissionChanged:(OSPermissionState * _Nonnull)state;
91+
@protocol OSNotificationPermissionObserver <NSObject>
92+
- (void)onNotificationPermissionDidChange:(BOOL)permission;
9293
@end
9394

94-
typedef OSObservable<NSObject<OSPermissionObserver>*, OSPermissionState*> ObservablePermissionStateChangesType;
95+
typedef OSBoolObservable<NSObject<OSNotificationPermissionObserver>*> ObservablePermissionStateChangesType;
9596

9697

9798
@interface OSPermissionChangedInternalObserver : NSObject<OSPermissionStateObserver>

iOS_SDK/OneSignalSDK/OneSignalNotifications/OSPermission.m

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,11 @@ - (void)onChanged:(OSPermissionStateInternal*)state {
196196
}
197197

198198
+ (void)fireChangesObserver:(OSPermissionStateInternal*)state {
199-
OSPermissionState *externalToState = [state getExternalState];
200-
OSPermissionState *externalFromState = [OSNotificationsManager.lastPermissionState getExternalState];
201-
202-
if (externalToState.permission == externalFromState.permission) {
199+
if (state.reachable == OSNotificationsManager.lastPermissionState.reachable) {
203200
return;
204201
}
205202

206-
BOOL hasReceiver = [OSNotificationsManager.permissionStateChangesObserver notifyChange:externalToState];
203+
BOOL hasReceiver = [OSNotificationsManager.permissionStateChangesObserver notifyChange:state.reachable];
207204
if (hasReceiver) {
208205
OSNotificationsManager.lastPermissionState = [state copy];
209206
[OSNotificationsManager.lastPermissionState persistAsFrom];

0 commit comments

Comments
 (0)