Skip to content

Commit 16d631d

Browse files
authored
Log out: Ensure that unregistering push notifications completes (#16386)
2 parents 4ee1f12 + 5f51a1d commit 16d631d

File tree

7 files changed

+30
-18
lines changed

7 files changed

+30
-18
lines changed

RELEASE-NOTES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- [*] Better support site credential login for sites with captcha plugins [https://github.com/woocommerce/woocommerce-ios/pull/16372]
77
- [*] Crash fix attempt to resolve the race condition in request authenticator swapping [https://github.com/woocommerce/woocommerce-ios/pull/16370]
88
- [*] Update products on the Top Performers card when there are changes made to displayed products [https://github.com/woocommerce/woocommerce-ios/pull/16380]
9+
- [*] Fixed issue unregistering device from push notifications [https://github.com/woocommerce/woocommerce-ios/pull/16386]
910
- [Internal] Fix broken navigation to a variable product selector [https://github.com/woocommerce/woocommerce-ios/pull/16363]
1011

1112
23.7

WooCommerce/Classes/Notifications/PushNotificationsManager.swift

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,18 +167,19 @@ extension PushNotificationsManager {
167167

168168
/// Unregisters the Application from WordPress.com Push Notifications Service.
169169
///
170-
func unregisterForRemoteNotifications() {
170+
func unregisterForRemoteNotifications(onCompletion: @escaping () -> Void) {
171171
DDLogInfo("📱 Unregistering For Remote Notifications...")
172172

173173
unregisterDotcomDeviceIfPossible() { error in
174174
if let error = error {
175175
DDLogError("⛔️ Unable to unregister from WordPress.com Push Notifications: \(error)")
176-
return
176+
} else {
177+
DDLogInfo("📱 Successfully unregistered from WordPress.com Push Notifications!")
178+
self.deviceID = nil
179+
self.deviceToken = nil
177180
}
178-
179-
DDLogInfo("📱 Successfully unregistered from WordPress.com Push Notifications!")
180-
self.deviceID = nil
181-
self.deviceToken = nil
181+
// Always call completion, even on error
182+
onCompletion()
182183
}
183184
}
184185

@@ -249,7 +250,7 @@ extension PushNotificationsManager {
249250
///
250251
func registrationDidFail(with error: Error) {
251252
DDLogError("⛔️ Push Notifications Registration Failure: \(error)")
252-
unregisterForRemoteNotifications()
253+
unregisterForRemoteNotifications {}
253254
}
254255

255256
/// Handles a notification while the app is in foreground

WooCommerce/Classes/ServiceLocator/PushNotesManager.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ protocol PushNotesManager {
5050
func registerForRemoteNotifications()
5151

5252
/// Unregisters the Application from WordPress.com Push Notifications Service.
53+
/// - Parameter onCompletion: Closure to be executed on completion.
5354
///
54-
func unregisterForRemoteNotifications()
55+
func unregisterForRemoteNotifications(onCompletion: @escaping () -> Void)
5556

5657
/// Requests Authorization to receive Push Notifications, *only* when the current Status is not determined.
5758
///

WooCommerce/Classes/Yosemite/AuthenticatedState.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,11 +237,6 @@ class AuthenticatedState: StoresManagerState {
237237
/// Executed before the current state is deactivated.
238238
///
239239
func willLeave() {
240-
let pushNotesManager = ServiceLocator.pushNotesManager
241-
242-
pushNotesManager.unregisterForRemoteNotifications()
243-
pushNotesManager.resetBadgeCountForAllStores(onCompletion: {})
244-
245240
resetServices()
246241
}
247242

WooCommerce/Classes/Yosemite/DefaultStoresManager.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ class DefaultStoresManager: StoresManager {
270270
sessionManager.deleteApplicationPassword(locally: true)
271271
ServiceLocator.analytics.refreshUserData()
272272
ZendeskProvider.shared.reset()
273-
ServiceLocator.pushNotesManager.unregisterForRemoteNotifications()
273+
ServiceLocator.pushNotesManager.unregisterForRemoteNotifications {}
274274
}
275275

276276
/// Fully deauthenticates the user, if needed.
@@ -290,6 +290,20 @@ class DefaultStoresManager: StoresManager {
290290
///
291291
@discardableResult
292292
func deauthenticate() -> StoresManager {
293+
let pushNotesManager = ServiceLocator.pushNotesManager
294+
pushNotesManager.resetBadgeCountForAllStores(onCompletion: {})
295+
296+
// Keep a strong reference to the current state to prevent it from being deallocated
297+
// until the unregister completes
298+
let currentState = state
299+
300+
// Unregister from remote notifications asynchronously
301+
pushNotesManager.unregisterForRemoteNotifications {
302+
DDLogInfo("📱 Push notification unregistration completed after logout")
303+
// Keep `currentState` until the end of the closure
304+
_ = currentState
305+
}
306+
293307
applicationPasswordGenerationFailureObserver = nil
294308
invalidWPCOMTokenNotificationObserver = nil
295309
stopObservingNetworkNotifications()

WooCommerce/WooCommerceTests/Mocks/MockPushNotificationsManager.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ final class MockPushNotificationsManager: PushNotesManager {
7878

7979
}
8080

81-
func unregisterForRemoteNotifications() {
81+
func unregisterForRemoteNotifications(onCompletion: @escaping () -> Void) {
8282

8383
}
8484

WooCommerce/WooCommerceTests/Notifications/PushNotificationsManagerTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ final class PushNotificationsManagerTests: XCTestCase {
134134
///
135135
func testUnregisterForRemoteNotificationsDoesNothingWhenThereIsNoDeviceIdStored() {
136136
XCTAssert(storesManager.receivedActions.isEmpty)
137-
manager.unregisterForRemoteNotifications()
137+
manager.unregisterForRemoteNotifications {}
138138
XCTAssert(storesManager.receivedActions.isEmpty)
139139
}
140140

@@ -143,7 +143,7 @@ final class PushNotificationsManagerTests: XCTestCase {
143143
///
144144
func testUnregisterForRemoteNotificationsEffectivelyDispatchesUnregisterDeviceAction() {
145145
defaults.set(Sample.deviceID, forKey: .deviceID)
146-
manager.unregisterForRemoteNotifications()
146+
manager.unregisterForRemoteNotifications {}
147147

148148
guard case let .unregisterDevice(deviceID, _) = storesManager.receivedActions.first as! NotificationAction else {
149149
XCTFail()
@@ -161,7 +161,7 @@ final class PushNotificationsManagerTests: XCTestCase {
161161
defaults.set(Sample.deviceID, forKey: .deviceID)
162162
defaults.set(Sample.deviceToken, forKey: .deviceToken)
163163

164-
manager.unregisterForRemoteNotifications()
164+
manager.unregisterForRemoteNotifications {}
165165

166166
guard case let .unregisterDevice(_, onCompletion) = storesManager.receivedActions.first as! NotificationAction else {
167167
XCTFail()

0 commit comments

Comments
 (0)