Skip to content

Commit

Permalink
Merge pull request #826 from ably/fix-push-state-machine
Browse files Browse the repository at this point in the history
Push State Machine: main thread sometimes gets stuck when accessing Local Device
  • Loading branch information
ricardopereira authored Jan 21, 2019
2 parents 583d896 + f4525fd commit e0c8277
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 81 deletions.
26 changes: 22 additions & 4 deletions Source/ARTPush.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
#import "ARTJsonLikeEncoder.h"
#import "ARTEventEmitter.h"
#if TARGET_OS_IOS
#import "ARTPushActivationStateMachine.h"
#import <UIKit/UIKit.h>
#import "ARTPushActivationStateMachine+Private.h"
#endif
#import "ARTPushAdmin.h"
#import "ARTPushActivationEvent.h"
Expand Down Expand Up @@ -55,7 +56,6 @@ - (ARTPushActivationStateMachine *)activationMachine {
return activationMachineInstance;
}


+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceTokenData rest:(ARTRest *)rest {
// HEX string, i.e.: <12ce7dda 8032c423 8f8bd40f 3484e5bb f4698da5 8b7fdf8d 5c55e0a2 XXXXXXXX>
// Normalizing token by removing symbols and spaces, i.e.: 12ce7dda8032c4238f8bd40f3484e5bbf4698da58b7fdf8d5c55e0a2XXXXXXXX
Expand Down Expand Up @@ -87,11 +87,29 @@ + (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error realti
}

- (void)activate {
[[self activationMachine] sendEvent:[ARTPushActivationEventCalledActivate new]];
if (!self.activationMachine.delegate) {
dispatch_async(dispatch_get_main_queue(), ^{
// -[UIApplication delegate] is an UI API call
self.activationMachine.delegate = UIApplication.sharedApplication.delegate;
[self.activationMachine sendEvent:[ARTPushActivationEventCalledActivate new]];
});
}
else {
[self.activationMachine sendEvent:[ARTPushActivationEventCalledActivate new]];
}
}

- (void)deactivate {
[[self activationMachine] sendEvent:[ARTPushActivationEventCalledDeactivate new]];
if (!self.activationMachine.delegate) {
dispatch_async(dispatch_get_main_queue(), ^{
// -[UIApplication delegate] is an UI API call
self.activationMachine.delegate = UIApplication.sharedApplication.delegate;
[self.activationMachine sendEvent:[ARTPushActivationEventCalledDeactivate new]];
});
}
else {
[self.activationMachine sendEvent:[ARTPushActivationEventCalledDeactivate new]];
}
}

#endif
Expand Down
103 changes: 27 additions & 76 deletions Source/ARTPushActivationStateMachine.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#import "ARTNSMutableRequest+ARTPush.h"

#if TARGET_OS_IOS
#import <UIKit/UIKit.h>

NSString *const ARTPushActivationCurrentStateKey = @"ARTPushActivationCurrentState";
NSString *const ARTPushActivationPendingEventsKey = @"ARTPushActivationPendingEvents";
Expand Down Expand Up @@ -133,16 +132,7 @@ - (void)deviceRegistration:(ARTErrorInfo *)error {
#if TARGET_OS_IOS
ARTLocalDevice *local = _rest.device_nosync;

__block id delegate;
if (self.delegate) {
delegate = self.delegate;
}
else {
dispatch_sync(_userQueue, ^{
// -[UIApplication delegate] is an UI API call
delegate = UIApplication.sharedApplication.delegate;
});
}
__block id delegate = self.delegate;

if (![delegate conformsToProtocol:@protocol(ARTPushRegistererDelegate)]) {
[NSException raise:@"ARTPushRegistererDelegate must be implemented on AppDelegate" format:@""];
Expand Down Expand Up @@ -202,16 +192,7 @@ - (void)deviceUpdateRegistration:(ARTErrorInfo *)error {
#if TARGET_OS_IOS
ARTLocalDevice *local = _rest.device_nosync;

__block id delegate;
if (self.delegate) {
delegate = self.delegate;
}
else {
dispatch_sync(_userQueue, ^{
// -[UIApplication delegate] is an UI API call
delegate = UIApplication.sharedApplication.delegate;
});
}
__block id delegate = self.delegate;

if (![delegate conformsToProtocol:@protocol(ARTPushRegistererDelegate)]) {
[NSException raise:@"ARTPushRegistererDelegate must be implemented on AppDelegate" format:@""];
Expand Down Expand Up @@ -278,16 +259,7 @@ - (void)deviceUnregistration:(ARTErrorInfo *)error {
#if TARGET_OS_IOS
ARTLocalDevice *local = _rest.device_nosync;

__block id delegate;
if (self.delegate) {
delegate = self.delegate;
}
else {
dispatch_sync(_userQueue, ^{
// -[UIApplication delegate] is an UI API call
delegate = UIApplication.sharedApplication.delegate;
});
}
__block id delegate = self.delegate;

// Custom register
SEL customDeregisterMethodSelector = @selector(ablyPushCustomDeregister:deviceId:callback:);
Expand Down Expand Up @@ -334,64 +306,43 @@ - (void)deviceUnregistration:(ARTErrorInfo *)error {

- (void)callActivatedCallback:(ARTErrorInfo *)error {
#if TARGET_OS_IOS
dispatch_async(_userQueue, ^{
id delegate;
if (self.delegate) {
delegate = self.delegate;
}
else {
delegate = UIApplication.sharedApplication.delegate;
}

if ([delegate conformsToProtocol:@protocol(ARTPushRegistererDelegate)]) {
SEL activateCallbackMethodSelector = @selector(didActivateAblyPush:);
if ([delegate respondsToSelector:activateCallbackMethodSelector]) {
[delegate didActivateAblyPush:error];
dispatch_async(_userQueue, ^{
id delegate = self.delegate;
if ([delegate conformsToProtocol:@protocol(ARTPushRegistererDelegate)]) {
SEL activateCallbackMethodSelector = @selector(didActivateAblyPush:);
if ([delegate respondsToSelector:activateCallbackMethodSelector]) {
[delegate didActivateAblyPush:error];
}
}
}
});
});
#endif
}

- (void)callDeactivatedCallback:(ARTErrorInfo *)error {
#if TARGET_OS_IOS
dispatch_async(_userQueue, ^{
id delegate;
if (self.delegate) {
delegate = self.delegate;
}
else {
delegate = UIApplication.sharedApplication.delegate;
}

if ([delegate conformsToProtocol:@protocol(ARTPushRegistererDelegate)]) {
SEL deactivateCallbackMethodSelector = @selector(didDeactivateAblyPush:);
if ([delegate respondsToSelector:deactivateCallbackMethodSelector]) {
[delegate didDeactivateAblyPush:error];
dispatch_async(_userQueue, ^{
id delegate = self.delegate;
if ([delegate conformsToProtocol:@protocol(ARTPushRegistererDelegate)]) {
SEL deactivateCallbackMethodSelector = @selector(didDeactivateAblyPush:);
if ([delegate respondsToSelector:deactivateCallbackMethodSelector]) {
[delegate didDeactivateAblyPush:error];
}
}
}
});
});
#endif
}

- (void)callUpdateFailedCallback:(nullable ARTErrorInfo *)error {
#if TARGET_OS_IOS
dispatch_async(_userQueue, ^{
id delegate;
if (self.delegate) {
delegate = self.delegate;
}
else {
delegate = UIApplication.sharedApplication.delegate;
}

if ([delegate conformsToProtocol:@protocol(ARTPushRegistererDelegate)]) {
SEL updateFailedCallbackMethodSelector = @selector(didAblyPushRegistrationFail:);
if ([delegate respondsToSelector:updateFailedCallbackMethodSelector]) {
[delegate didAblyPushRegistrationFail:error];
dispatch_async(_userQueue, ^{
id delegate = self.delegate;
if ([delegate conformsToProtocol:@protocol(ARTPushRegistererDelegate)]) {
SEL updateFailedCallbackMethodSelector = @selector(didAblyPushRegistrationFail:);
if ([delegate respondsToSelector:updateFailedCallbackMethodSelector]) {
[delegate didAblyPushRegistrationFail:error];
}
}
}
});
});
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion Source/ARTRest.m
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ - (ARTLocalDevice *)device {
// Store address of once_token to access it in debug function.
static dispatch_once_t *device_once_token;

- (NSString *)device_nosync {
- (ARTLocalDevice *)device_nosync {
static dispatch_once_t once;
device_once_token = &once;
static id device;
Expand Down

0 comments on commit e0c8277

Please sign in to comment.