Keeping my WatchKit complications up to date when

2019-04-11 03:39发布

I'm working on the WatchKit Extension of my app, and have some issues with complications.

I have a complication that displays a given total amount, which depends of what the user is doing on the iOS app. When the WatchKit Extension is running, the iOS app updates the watch app context using the -[WCSession updateApplicationContext:] method. It works fine, and then in the ExtensionDelegate of my Watch app, I manually update the complication with the new data.

But this is OK only when the extension is running (if it's not, it won't get the application context until the next launch).

So I edited my code to send the complication data directly to the Watch when user changed something in the iOS app, using the -[WCSession transferCurrentComplicationUserInfo:] method (it's written in the documentation that the ExtensionDelegate should be woken up to receive the user info in background).

I've implemented the -session:didReceiveUserInfo: method of the ExtensionDelegate to update the complication when it received data from the iOS app, but it doesn't work when the extension is not running... (and I don't know if it ever receives the user info as I can't log it)

How should I do to keep my complications up to date even when the extension is not running??

Thanks

PS: I'm using the Watch Simulator, and to "close" the extension I just Reboot the Watch (from the Hardware menu)

Edit: I managed to log out statements when the app is not running (by opening the Watch Simulator system log), and I get these lines when the iOS send a new complication user data to the watch extension:

Oct 18 18:08:11 pc16 WatchApp Extension[26615]: Extension received request to wake up for complication support.

Oct 18 18:08:11 pc16 assertiond[26585]: assertion failed: 15A284 13S343: assertiond + 15398 [B48FCADB-A071-3A46-878B-538DC0AFF60B]: 0x1

So the watch receives well the user info dictionary, but seems to fail waking up the extension...

Edit 2: here is the part of code in the ExtensionDelegate that should receive the complication user info (but which is not called when the app is not running):

- (void) session: (WCSession *)session didReceiveUserInfo: (NSDictionary *)userInfo
{
    NSLog(@"session:didReceiveUserInfo: %@", userInfo);

    NSString *userInfoType = userInfo[KHWASessionTransferUserInfoType];
    NSDictionary *userInfoContents = userInfo[KHWASessionTransferUserInfoContents];

    // Complication Data
    if ([userInfoType isEqualToString:KHWASessionTransferUserInfoTypeComplicationData]) {

        // Store the complication data into user defaults
        [[NSUserDefaults standardUserDefaults] setValue:userInfoContents[KHWAComplicationTotalBalance] forKey:KHWAComplicationTotalBalance];
        [[NSUserDefaults standardUserDefaults] synchronize];

        // And refresh the complications
        CLKComplicationServer *complicationServer = [CLKComplicationServer sharedInstance];
        for (CLKComplication *complication in complicationServer.activeComplications) {
            [complicationServer reloadTimelineForComplication:complication];
        }
    }
}

Edit 3: the WCSession is set in the extension delegate applicationDidFinishLaunching method:

- (void) applicationDidFinishLaunching
{
    // Setup the WatchConnectivity session
    WCSession *session = [WCSession defaultSession];
    session.delegate = self;
    [session activateSession];

    [...]
}

1条回答
男人必须洒脱
2楼-- · 2019-04-11 03:56

Wow, I finally resolved the issue!

It seems that, even if I didn't see it in the log files (see my last comment), the init method of WCExtensionDelegate is well called when waking up the app.

So I just had to move the WCSession setting bloc into the init method :

- (id) init
{
    if (self = [super init]) {

        // Setup the WatchConnectivity session
        WCSession *session = [WCSession defaultSession];
        session.delegate = self;
        [session activateSession];
    }

    return self;
}

And for the while it works fine...

查看更多
登录 后发表回答