0

I am attempting to send data from iOS -> Watch and this works fine when the active controller has didReceiveApplicationContext implemented. I can receive the context object and everything works well.

However, I'm not clear how I can implement didReceiveApplicationContext "globally" so that the Watch is capturing context data changes from iOS irrespective of which controller the user is on. I have several controllers that the user can navigate across so when they are on a controller that doesn't have this delegate method, no data is captured.

I've tried to add this delegate method to ExtensionDelegate.m in an attempt to capture data coming from iOS globally but it doesn't seem to capture anything when I try to output to log.

I'm assuming there's a way to achieve this without implementing didReceiveApplicationContext in every single Watch controller?

Thanks

joern
  • 27,354
  • 7
  • 90
  • 105
GivP
  • 2,634
  • 6
  • 32
  • 34

1 Answers1

3

You can create a delegate class that listens for new data and then informs all interested interface controllers about the new data. If you have multiple interface controllers that need to be updated when new data arrives you can implement this delegate as singleton to be able to add observers from any part of your extension (like Apple does with its NSNotificationCenter class):

class SessionDelegate {
    static let sharedDelegate = SessionDelegate()
    private override init() {}
    ....
}

Define a observer protocol that all interested interface controllers can implement:

protocol DataObserver {
    func dataDidChange(data: AnyObject)
}

Add an observer array to your delegate class and two methods to add and remove observers:

private var observers = [DataObserver]()

func addObserver(observer: DataObserver) {
   // add the observer to observers
}

func removeObserver(observer: DataObserver) {
   // remove the observer from observers
}

When you receive new data iterate through the observers and call the method defined in the protocol:

func didReceiveData(data: AnyObject) {
    for observer in observers {
        observer.dataDidChange(data)
    }
}

Now all WKInterfaceController classes that need to refresh can add themselves as observers:

SessionDelegate.sharedDelegate.addObserver(self)

And implement the method from the protocol:

func dataDidChange(data: AnyObject) {
    // update UI
}

Finally you have to inform your delegate class that new data has arrived, so that it can inform its observers. So implement didReceiveApplicationContext in your ExtensionDelegate and call dataDidChange on your delegate class:

extension ExtensionDelegate: WCSessionDelegate {
    func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]) {
        SessionDelegate.sharedDelegate.dataDidChange(applicationContext)
    }
}
joern
  • 27,354
  • 7
  • 90
  • 105
  • I have been pulling my hair out on this topic for days. 2 questions. In the ExtensionDelegate: WCSessionDelegate, shouldn't it be didReceiveData instead of dataDidChange? Second - I get an error when I put the SessionDelegate.sharedDelegate.addObserver(self) to my GlanceController, even though I've put in the dataDidChange method. Is there something else I need to do with a WKInterfaceController to get rid of the error? ("GlanceController" does not conform to expected type "DataObserver") – ShadowDES Oct 24 '15 at 03:54
  • class GlanceController: WKInterfaceController, DataObserver <-- I forgot to add .... Now it works like a charm. Thanks for the answer :) – ShadowDES Oct 24 '15 at 04:05