Apple Local Push Connectivity with error nil?

I'm trying to configure Local Push Connectivity. I already have Local Push Entitlement, and have install a provisioning profile with local push entitlement. It's build fine but when app start, PushProvider didn't active and start and Push Manager show error nil. I have done every instructions that sample code have provided.

This is my project. In my application target, I have a bundle id com.my_team_name.my_app_name and in the app group name group.com.my_team_name.my_app_name

In the .entitlement, I've set the required configuration:

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.networking.networkextension</key>
    <array>
        <string>app-push-provider</string>
    </array>
    <key>com.apple.developer.networking.wifi-info</key>
    <true/>
    <key>com.apple.security.application-groups</key>
    <array>
        <string>group.com.my_team_name.my_app_name</string>
    </array>
</dict>
</plist>

Info.plist has noting to change And I have a PushManager Class with this code

class AppPushManager: NSObject, NEAppPushDelegate{
    func appPushManager(_ manager: NEAppPushManager, didReceiveIncomingCallWithUserInfo userInfo: [AnyHashable : Any] = [:]) {
        
    }
    
    static let shared = AppPushManager()
    
    private var pushManager: NEAppPushManager = NEAppPushManager()
    private let pushManagerDescription = "PushDefaultConfiguration"
    private let pushProviderBundleIdentifier = "com.my_team_name.my_app_name.PushProvider"
    
    func initialize() {
        if pushManager.delegate == nil {
            pushManager.delegate = self
        }
        
        pushManager.localizedDescription = pushManagerDescription
        pushManager.providerBundleIdentifier = pushProviderBundleIdentifier
        pushManager.isEnabled = true

        pushManager.providerConfiguration = [
            "host": "my_server.local"
        ]

        pushManager.matchSSIDs = ["my_wifi_ssid"]
        
        pushManager.saveToPreferences(completionHandler: { error in
            print("error? \(String(describing: error))")
            print("is active: \(pushManager.isActive)")
        })
    }
}

In my extension, A PushProvider Target. I have a bundle id com.my_team_name.my_app_name.PushProvider

and in the app group name group.com.my_team_name.my_app_name

In the Info.plist of my extension, I've added the required configuration:

<key>NSExtension</key>
<dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.networkextension.app-push</string>
    <key>NSExtensionPrincipalClass</key>
    <string>$(PRODUCT_MODULE_NAME).PushProvider</string>
</dict>

the .entitlement file have the same contents as the application. and I have created the extension class "PushProvider.swift" as follow:

class PushProvider: NEAppPushProvider {
    ...
}

When I run the application, I got this printed out

error? nil
is active: false

I think it might be something with providerBundleIdentifier in Push Manager. Have anyone know what I've missing?

Answered by BizarreTH in 713698022

Seem to working now I'm confuse with 'pushManager.isActive` always show false, but it actually run. Debugging by this method https://developer.apple.com/forums/thread/11241?answerId=32880022#32880022 help me a lot.

I would make sure that you are running this project on a development device with the debugger attached, and the console.app window filtering the logs from your app. That should tell you what is happening here.

From the container app, make sure that you are going through the path of:

  1. loadAllFromPreferences to create the initial NEAppPushManager:
private var pushManager: NEAppPushManager?

...

NEAppPushManager.loadAllFromPreferences { managers, error in
    precondition(Thread.isMainThread)
    if let error = error {
        os_log("Error loading NEAppPushManager: %{public}@", error.localizedDescription)
        return
    }

    var manager: NEAppPushManager
    if let foundManager = managers?.first, NetworkManager.isOurManager(foundManager) {
        manager = foundManager
        os_log("Did find an existing NEAppPushManager, assigning the instance")
    } else {
        manager = NEAppPushManager()
        os_log("Did not find a NEAppPushManager, creating a new instance")
    }
    manager.delegate = self
    self.pushManager = manager
    
    // Setup Push Manager
    self.pushManager?.localizedDescription = ""
    self.pushManager?.providerBundleIdentifier = "com.my_team_name.my_app_name.PushProvider"
    self.pushManager?.isEnabled = true
    self.pushManager?.providerConfiguration = [
        "host": "hostinfo.com"
    ]
    self.pushManager?.matchSSIDs = ["NetworkSSID"]
    
}

  1. Then load and save the NEAppPushManager:
guard let localManager = self.pushManager else {
    // Handle the failed unwrap
    return
}

localManager.loadFromPreferences { error in
    precondition(Thread.isMainThread)
    
    if let error = error {
        os_log("Error loading NEAppPushManager: %{public}@", error.localizedDescription)
        // Handle error
        return
    }
    
    localManager.saveToPreferences { error in
        if let nsError = error as NSError? {
            os_log("did not save configuration, error: %{public}@", nsError.localizedDescription)
            // Handle error
            return
        }
        os_log("Did Save Configuration Successfully")
        // Checkout logs here
    }
}
  1. Configure the NEAppPushProvider with a constructor to see if it is even being reached after the saveToPreferences call.
class PushProvider: NEAppPushProvider {
   
    override init() {
        os_log("AppPushProvider init")
        super.init()
    }
    
    // MARK: - NEAppPushProvider Life Cycle
    

    override func start(completionHandler: @escaping (Error?) -> Void) {
        os_log("AppPushProvider start")
        
        completionHandler(error)
    }
    ...
}

Try this out and see where this gets you.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

After a lot of trying I found that error

<NEAppPushManager: 0x281512160>: Failed to save the configuration: Error Domain=NEConfigurationErrorDomain Code=9 "configuration is unchanged" UserInfo={NSLocalizedDescription=configuration is unchanged}

it is what it means. When I change setting, error disappears. But PushProvider still not active. both function override init()  and 'override func start()' in PushProvider class was not executed at all.

When I change setting, error disappears. But PushProvider still not active. both function override init() and 'override func start()' in PushProvider class was not executed at all.

Right, it does sound like you have a configuration issue here if your can execute saveToPreferences without an error but the provider is not being hit at all.

Are there any other logs that may indicate what is happening in the Console.app? I would recommend deleting the app and network configuration entirely from your test device and then start over again. Then, reproduce the error while your device is recording logs to the console and see if that gives you any more clues as to what is happening.

Accepted Answer

Seem to working now I'm confuse with 'pushManager.isActive` always show false, but it actually run. Debugging by this method https://developer.apple.com/forums/thread/11241?answerId=32880022#32880022 help me a lot.

Apple Local Push Connectivity with error nil?
 
 
Q