Skip to content

FIRInstanceID.instanceIDWithHandler() handler is not called if unregisterForRemoteNotifications() has previously been called more than once #3229

Closed
@jasongiss

Description

  • Xcode version: 10.2.1
  • Firebase SDK version: 6.2.0
  • Firebase Component: Messaging
  • Component version: 4.0.2

[REQUIRED] Step 3: Describe the problem

The instanceIDWithHandler() method of FIRInstanceID docs say that the handler will always be called. However, seemingly if you have previously called your Application's unregisterForRemoteNotifications() twice, then the handler is never called.

This is happening in my application as I allow the user to enable/disable notifications from within the app, and if they turn them off and on a few times, the callback handler is never called and so things lock up.

The docs say that you should be able to call this at any point to get the current token, rather than storing it yourself.
(The anchor link I have used doesn't seem to work - I am referring to the "Fetching the current registration token" section)

Steps to reproduce:

I've created a simple test project which shows the problem, which is attached.
FirebaseMessagingTest.zip

  • Add your own GoogleService-Info.plist, and change the Bundle Identifier accordingly.
  • Run pod install to install the Firbase SDK via Cocoapods.
  • Run the app, with device attached, click the button to enable/disable notifications several times.
  • Watch the Output window in Xcode for log messages: Once it goes wrong, you'll see it starts fetching the token, but never finishes.

Relevant Code:

Alternatively, below is the code (minus the delegates):

class ViewController: UIViewController {
	
	typealias CompletionHandler = (_ success: Bool, _ error: Error?) -> Void
	
	private var mNotificationsEnabled = false

	override func viewDidLoad() {
		super.viewDidLoad()
		
		FirebaseApp.configure()
	}

	@IBAction func ButtonPressed(_ sender: UIButton) {
		mNotificationsEnabled = !mNotificationsEnabled
		let newTitle = mNotificationsEnabled ? "Disable Notifications" : "Enable Notifications"
		sender.setTitle(newTitle, for: .normal)
		sender.isEnabled = false
		
		setNotifications(enabled: mNotificationsEnabled, completionHandler: { (success, error) in
			sender.isEnabled = true
		})
	}
	
	func setNotifications(enabled: Bool, completionHandler: @escaping CompletionHandler) {
		if (enabled) {
			enableNotifications(completionHandler: {(success, error) in
				self.getToken(completionHandler)
			})
		}
		else {
			disableNotifications(completionHandler: completionHandler)
		}
	}
	
	func enableNotifications(completionHandler: @escaping CompletionHandler) {
		print("Enabling...")
		
		let notificationCenter = UNUserNotificationCenter.current()
		notificationCenter.requestAuthorization(options: [.alert, .sound, .badge], completionHandler: {(success, error) in
			if (success) {
				notificationCenter.delegate = self;
				Messaging.messaging().delegate = self
				
				DispatchQueue.main.async(execute: {
					UIApplication.shared.registerForRemoteNotifications() // Must run on main thread
					print("Notifications Enabled")
					completionHandler(success, error)
				})
				
			}
			else {
				print("Enabling failed")
				completionHandler(false, error)
			}
		})
	}
	
	func disableNotifications(completionHandler: @escaping CompletionHandler) {
		print("Disabling...")
		
		DispatchQueue.main.async(execute: {
			UIApplication.shared.unregisterForRemoteNotifications() // Must run on main thread
			print("Notifications Disabled")
			completionHandler(true, nil)
		})
	}
	
	func getToken(_ completionHandler: @escaping CompletionHandler) {
		print("Fetching Token...")
		
		//MARK: BUG? The following never calls its handler if invoked after unregisterForRemoteNotifications() has been called twice.
		InstanceID.instanceID().instanceID(handler: { (result, error) in
			if let error = error {
				print("Error fetching remote instance ID: \(error)")
				completionHandler(false, error)
			}
			else if let result = result {
				print("Token found")
				completionHandler(true, nil)
			}
		})
	}
	
}

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions