When I add the PushKit delegates in the App Delegate, it works perfectly. Here's the code:
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
self.voipRegistration()
return true
}
// Register for VoIP notifications
func voipRegistration() {
// Create a push registry object
let mainQueue = DispatchQueue.main
let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
voipRegistry.delegate = self
voipRegistry.desiredPushTypes = [.voIP]
}
}
// MARK: - PKPushRegistryDelegate
extension AppDelegate : PKPushRegistryDelegate {
// Handle updated push credentials
func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
let deviceToken = credentials.token.map { String(format: "%02x", $0) }.joined()
print("pushRegistry -> deviceToken :\(deviceToken)")
}
func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
print("pushRegistry:didInvalidatePushTokenForType:")
}
// Handle incoming pushes
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
// Show call screen
if type == .voIP {
print("VoIP")
} else {
print("Nope")
}
if UIApplication.shared.applicationState == UIApplication.State.active {
print("Active")
} else {
let config = CallKit.CXProviderConfiguration()
config.supportsVideo = true
let provider = CXProvider(configuration: config)
let testCallKit = TestCallKitFile()
testCallKit.recieveACall(provider: provider)
}
}
}
This code works because a token is being printed from the didUpdate credentials
method. But when I put the delegate methods in a separate class, they are not being called (I know that because the token is not being printed). Here's the code:
VoIPNotificationManager class
class VoIPNotificationManager: NSObject, PKPushRegistryDelegate {
func registerForVoIPNotifications() {
let mainQueue = DispatchQueue.main
let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
voipRegistry.delegate = self
voipRegistry.desiredPushTypes = [.voIP]
}
// Handle updated push credentials
func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
let deviceToken = credentials.token.map { String(format: "%02x", $0) }.joined()
print("pushRegistry -> deviceToken :\(deviceToken)")
}
func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
print("pushRegistry:didInvalidatePushTokenForType:")
}
// Handle incoming pushes
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
// Show call screen
if type == .voIP {
print("VoIP")
} else {
print("Nope")
}
if UIApplication.shared.applicationState == UIApplication.State.active {
print("Active")
} else {
let config = CallKit.CXProviderConfiguration()
config.supportsVideo = true
let provider = CXProvider(configuration: config)
let testCallKit = TestCallKitFile()
testCallKit.recieveACall(provider: provider)
}
}
}
And I am calling this in the appDelegate's didFinishLaunchingWithOptions
method like so:
// Register for voip notifs
let voipNotificationManager = VoIPNotificationManager()
voipNotificationManager.registerForVoIPNotifications()
Also, this is a SwiftUI app.
It looks like you don't store a reference to your voipNotificationManager
outside of the didFinishLaunchingWithOptions
method.
Am I right?
If so, the manager just gets deallocated after the didFinishLaunchingWithOptions
finishes. As there are no strong references left.
Here is how memory management works in swift link
What I would suggest you do is make your voipNotificationManager
a property on the app delegate like so
class AppDelegate: UIResponder, UIApplicationDelegate {
let voipNotificationManager = VoIPNotificationManager()
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
voipNotificationManager.registerForVoIPNotifications()
return true
}
...
}