Apples docs are a bit vague on when a device's deviceToken can change. It pays to code defensively, and to test that code.
I've written my app so that at startup it registers for push notifications and handles the didRegisterForRemoteNotificationsWithDeviceToken
callback.
My didRegisterForRemoteNotificationsWithDeviceToken
saves the last device token to user defaults, and if the token is still the same, it moves on. If it doesn't have a saved token at all, or if the tokens don't match, it uploads the new token our server.
I also have a mechanism that lets me name my test devices with human-readable names like "4s_1" "5s_1" "5s_2", etc. I have a server command line tool that takes the human-readable device name, looks up the device's 'identifierForVendor' from that, and then looks up the device token using the identifier. It then triggers a sandbox notification.
It seems that deleting the app and reinstalling it causes the 'identifierForVendor' to change, but not the deviceToken
, which is exactly the opposite of what I'd like to have happen for testing. I want some value that never changes to uniquely identify a test device, and away to change the device token so I can test my code.
EDIT: Since writing this I've changed the app to generate it's own UUID and save that to the keychain as suggested by Wain in his answer.
Is there a way to force Apple's APNs to change a device's token so I can test out my code (both client side and server side) for handling the case where the token changes?
I don't believe so.
If you want a single unique identifier then you should create one explicitly and store it in the keychain, then you can store the device name and all other details against this so you have a single point of truth.
Any identifier you stored in the keychain would survive until it was explicitly removed or the device was restored from a backup without that keychain content.