@@ -82,6 +82,10 @@ public class PushNotificationManager: NSObject {
8282 private var restClient : RestClient ?
8383 private var preferences : SFPreferences ?
8484
85+ private var loginObserver : NSObjectProtocol ?
86+ private var logoutObserver : NSObjectProtocol ?
87+ private var enterForegroundObserver : NSObjectProtocol ?
88+
8589 /// Convenience initializer that sets up the PushNotificationManager with default values:
8690 /// - notificationRegister: DefaultRemoteNotificationRegistrar() - Handles APNS registration
8791 /// - restClient: RestClient.shared - Uses the shared RestClient instance
@@ -121,15 +125,14 @@ public class PushNotificationManager: NSObject {
121125 self . deviceToken = preferences? . string ( forKey: PushNotificationConstants . deviceToken)
122126 self . deviceSalesforceId = preferences? . string ( forKey: PushNotificationConstants . deviceSalesforceId)
123127
124- NotificationCenter . default. addObserver ( self ,
125- selector: #selector( onUserLoggedIn ( _: ) ) ,
126- name: NSNotification . Name ( rawValue: UserAccountManager . didLogInUser. rawValue) ,
127- object: nil )
128-
129- NotificationCenter . default. addObserver ( self ,
130- selector: #selector( onAppWillEnterForeground ( _: ) ) ,
131- name: UIApplication . willEnterForegroundNotification,
132- object: nil )
128+ setupNotificationObservers ( )
129+ }
130+
131+ deinit {
132+ let center = NotificationCenter . default
133+ center. removeObserver ( loginObserver ?? self )
134+ center. removeObserver ( logoutObserver ?? self )
135+ center. removeObserver ( enterForegroundObserver ?? self )
133136 }
134137
135138 /// Registers the app with Apple Push Notification Service (APNS).
@@ -305,6 +308,55 @@ public class PushNotificationManager: NSObject {
305308 return unregisterSalesforceNotifications ( for: user, completionBlock: completionBlock)
306309 }
307310
311+ /// Unregisters the device from Salesforce push notifications for a specific user.
312+ ///
313+ /// - Parameters:
314+ /// - user: The user account to unregister.
315+ /// - completionBlock: A block executed when unregistration is complete.
316+ /// - Returns: `true` if unregistration started successfully, otherwise `false`.
317+ @discardableResult
318+ @objc ( unregisterSalesforceNotificationsWithCompletionBlock: completionBlock: )
319+ public func unregisterSalesforceNotifications( for user: UserAccount ,
320+ completionBlock: ( ( ) -> Void ) ? ) -> Bool {
321+ guard deviceSalesforceId != nil else {
322+ completionBlock ? ( )
323+ return true
324+ }
325+
326+ if isSimulator {
327+ completionBlock ? ( )
328+ return true
329+ }
330+
331+ guard let prefs = preferences else {
332+ SFSDKCoreLogger . e ( Self . self, message: " Cannot unregister from notifications with Salesforce: no user prefs " )
333+ return false
334+ }
335+
336+ guard let sfId = prefs. string ( forKey: PushNotificationConstants . deviceSalesforceId) else {
337+ SFSDKCoreLogger . e ( Self . self, message: " Cannot unregister from notifications with Salesforce: no deviceSalesforceId " )
338+ return false
339+ }
340+
341+ let apiVersion = restClient? . apiVersion ?? SFRestDefaultAPIVersion
342+ let path = " / \( apiVersion) / \( PushNotificationConstants . endPoint) / \( sfId) "
343+ let request = RestRequest ( method: . DELETE,
344+ path: path,
345+ queryParams: nil )
346+ Task {
347+ do {
348+ _ = try await restClient? . send ( request: request)
349+ completionBlock ? ( )
350+ } catch {
351+ SFSDKCoreLogger . e ( Self . self, message: " Push notification unregistration failed: \( error. localizedDescription) " )
352+ completionBlock ? ( )
353+ }
354+ }
355+
356+ SFSDKCoreLogger . i ( Self . self, message: " Unregister from notifications with Salesforce sent " )
357+ return true
358+ }
359+
308360 /// Fetches and stores actionable notification types from the server or cache.
309361 ///
310362 /// - Parameters:
@@ -377,11 +429,47 @@ public class PushNotificationManager: NSObject {
377429 }
378430 self . unregisterForSalesforceNotifications ( user: currentUser, completionBlock)
379431 }
432+
433+ /// Unregister from Salesforce notfications for a specific user
434+ /// - Parameters:
435+ /// - user: The user that should be unregistered from notfications
436+ /// - completionBlock: completion block to call with success or failure
437+ public func unregisterForSalesforceNotifications( user: UserAccount , _ completionBlock: @escaping ( Bool ) -> ( ) ) {
438+ let result = unregisterSalesforceNotifications ( for: user) {
439+ completionBlock ( true )
440+ }
441+
442+ if ( !result) {
443+ completionBlock ( false )
444+ }
445+ }
446+
380447}
381448
382449private extension PushNotificationManager {
383- @objc private func onUserLoggedIn( _ notification: Notification ) {
450+
451+ private func setupNotificationObservers( ) {
452+ loginObserver = NotificationCenter . default. addObserver (
453+ forName: UserAccountManager . didLogInUser,
454+ object: nil ,
455+ queue: . main
456+ ) { [ weak self] in self ? . onUserLoggedIn ( $0) }
457+
458+ logoutObserver = NotificationCenter . default. addObserver (
459+ forName: UserAccountManager . didLogoutUser,
460+ object: nil ,
461+ queue: . main
462+ ) { [ weak self] in self ? . onUserLoggedOut ( $0) }
384463
464+ enterForegroundObserver = NotificationCenter . default. addObserver (
465+ forName: UIApplication . willEnterForegroundNotification,
466+ object: nil ,
467+ queue: . main
468+ ) { [ weak self] in self ? . onAppWillEnterForeground ( $0) }
469+ }
470+
471+ @objc private func onUserLoggedIn( _ notification: Notification ) {
472+ restClient = RestClient . shared
385473 if deviceToken != nil {
386474 SFSDKCoreLogger . i ( Self . self, message: " User logged in, registering push " )
387475 _ = registerSalesforceNotifications ( completionBlock: nil , failBlock: nil )
@@ -399,54 +487,7 @@ private extension PushNotificationManager {
399487 _ = registerSalesforceNotifications ( completionBlock: nil , failBlock: nil )
400488 }
401489
402- private func unregisterSalesforceNotifications( for user: UserAccount ,
403- completionBlock: ( ( ) -> Void ) ? ) -> Bool {
404- guard deviceSalesforceId != nil else {
405- completionBlock ? ( )
406- return true
407- }
408-
409- if isSimulator {
410- completionBlock ? ( )
411- return true
412- }
413-
414- guard let prefs = preferences else {
415- SFSDKCoreLogger . e ( Self . self, message: " Cannot unregister from notifications with Salesforce: no user prefs " )
416- return false
417- }
418-
419- guard let sfId = prefs. string ( forKey: PushNotificationConstants . deviceSalesforceId) else {
420- SFSDKCoreLogger . e ( Self . self, message: " Cannot unregister from notifications with Salesforce: no deviceSalesforceId " )
421- return false
422- }
423-
424- let apiVersion = restClient? . apiVersion ?? SFRestDefaultAPIVersion
425- let path = " / \( apiVersion) / \( PushNotificationConstants . endPoint) / \( sfId) "
426- let request = RestRequest ( method: . DELETE,
427- path: path,
428- queryParams: nil )
429- Task {
430- do {
431- _ = try await restClient? . send ( request: request)
432- completionBlock ? ( )
433- } catch {
434- SFSDKCoreLogger . e ( Self . self, message: " Push notification unregistration failed: \( error. localizedDescription) " )
435- completionBlock ? ( )
436- }
437- }
438-
439- SFSDKCoreLogger . i ( Self . self, message: " Unregister from notifications with Salesforce sent " )
440- return true
441- }
442-
443- private func unregisterForSalesforceNotifications( user: UserAccount , _ completionBlock: @escaping ( Bool ) -> ( ) ) {
444- let result = unregisterSalesforceNotifications ( for: user) {
445- completionBlock ( true )
446- }
447-
448- if ( !result) {
449- completionBlock ( false )
450- }
490+ @objc private func onUserLoggedOut( _ notification: Notification ) {
491+ restClient = RestClient . shared
451492 }
452493}
0 commit comments