WatchOS in simulator: clientIdentifier for interfaceControllerID not found

In this watch app, I have a session established with the iPhone.


When I tap on a button, it sends a request to the phone and receive data back. Very basic.


It works OK (as far as I can tell) on watch.


But I get the following error message on the simulator (XCode 10.1ß3), repeated a large number of times (probably for each message sent):

2019-04-26 23:01:37.507670+0200 App Watch Extension[29234:3427227] [default] -[SPRemoteInterface _interfaceControllerClientIDForControllerID:]:2140: ComF: clientIdentifier for interfaceControllerID:72320003 not found

followed by a last message

2019-04-26 23:21:42.509161+0200 App Watch Extension[29538:3481890] [default] _SendRecordedValues:363: ComF:<-Plugin controller ID 73620003 has no client identifier



I have identified the mentioned controller:

- I have a first controller, where the button is

- there is a second controller (with identifier "ID2") called from this first controller, with a table

- When I tap the button without having fone to second controller, no error

- When I go to second controller, then back to the first and tap, then the problem occurs

I have also noted that if I select Hardware > Lock in simulator menu, problem disappear.

Does it mean I have an object (the second controller) deallocated from memory ?


the IBAction for tap:

    @IBAction func tapOnVEForSelectInTable(_ sender: Any) {
        presentController(withName: "ID2", context: self)   
    }



I searched on forums and found this, which helped partly:

https://stackoverflow.com/questions/39610700/watch-app-starts-with-error-clientidentifier-for-interfacecontrollerid-not-found


It is said that the problem could come from deactivate method.

In fact, in this case, it does nothing:

    override func didDeactivate() {
        super.didDeactivate()
    }


The willActivate is pretty simple as well: in second controller

    override func willActivate() {

        super.willActivate()
       
        veTable.scrollToRow(at: indexAtCall)  // 26.4.2019
   }

In first controller


    override func willActivate() {
       
        super.willActivate()
        // Activate needed to display the VE by default on the watch
        if WCSession.isSupported() {
            let session = WCSession.default
            session.delegate = self

            if session.activationState != .activated {  // activate on the watch side
                session.activate()
            }
        }
    }


I am wondering where to look to isolate the problem.

Accepted Reply

It seems I've found the cause:


In fsecond controller, I did set a delegate property of the first controller


    override func awake(withContext context: Any?) {
       
        super.awake(withContext: context)
        callingDelegate = context as? GetSelectedDataDelegate
        guard let callingController = context as? SessionInterfaceController else { return }

        callingController.delegateForRowUpdate = self  // Caused problem when returning to first controller


And tyhis delegate did remain after second controller was dismissed.


I changed as follows and it works:


Added

   var callerController: SessionInterfaceController?  // 26.4.2019


Modified awake

    override func awake(withContext context: Any?) {
     
        super.awake(withContext: context)
        callingDelegate = context as? GetSelectedDataDelegate
        guard let callingController = context as? SessionInterfaceController else { return }

        callerController = callingController    // ADDED
        callingController.delegateForRowUpdate = self 



Then, in deactivate:


    override func didDeactivate() {

        super.didDeactivate()
        callerController?.delegateForRowUpdate = nil    //ADDED
    }

Replies

It seems I've found the cause:


In fsecond controller, I did set a delegate property of the first controller


    override func awake(withContext context: Any?) {
       
        super.awake(withContext: context)
        callingDelegate = context as? GetSelectedDataDelegate
        guard let callingController = context as? SessionInterfaceController else { return }

        callingController.delegateForRowUpdate = self  // Caused problem when returning to first controller


And tyhis delegate did remain after second controller was dismissed.


I changed as follows and it works:


Added

   var callerController: SessionInterfaceController?  // 26.4.2019


Modified awake

    override func awake(withContext context: Any?) {
     
        super.awake(withContext: context)
        callingDelegate = context as? GetSelectedDataDelegate
        guard let callingController = context as? SessionInterfaceController else { return }

        callerController = callingController    // ADDED
        callingController.delegateForRowUpdate = self 



Then, in deactivate:


    override func didDeactivate() {

        super.didDeactivate()
        callerController?.delegateForRowUpdate = nil    //ADDED
    }