WKExtensionDelegate handleActivity called twice when intent extension uses continueInApp

I'm using custom siri intents in my iOS and Watch app. Before working up to supporting full background execution in the intent extension I'm trying to always use a 'continueInApp' response code in the intent handler in my app extension. This works fine on iOS but on watchOS, the WKExtensionDelegate's handleActivity method is being called twice in quick succession each time I use Siri on the Watch to run my shortcut/intent.


I've tried passing a custom NSUserActivity when creating my response object, and by adding a timestamp in there I'm pretty confident that the intent handler is only being called once. But I see two calls to the handleActivity method in my extension delegate.


I'm not using the handleIntent extension delegate method. That never seems to be called and I suspect it might be for the non-custom SiriKit intents prior to iOS 12.


- (void)handleSelectTimerProfile:(nonnull POMSelectTimerProfileIntent *)intent completion:(nonnull void (^)(POMSelectTimerProfileIntentResponse * _Nonnull))completion
{
    completion([[POMSelectTimerProfileIntentResponse alloc] initWithCode:POMSelectTimerProfileIntentResponseCodeContinueInApp 
                                                            userActivity:nil]);
}

It doesn't seem to matter whether my 'confirm' or 'handle' method uses the continueInApp response code.

Replies

Also seeing this for voice shortcuts (useractivities). Did you create a rdar yet?

I haven't raised a Radar because they're just going to ask for a sample project, which would be an awful lot of work (Watch app, Intent extension on iOS and Watch and so on).


I worked round the issue by passing a userActivity when I have the Watch intent extension ask to continue in app. I put a timestamp string in the userInfo dictionary for the userActivity:



- (void)handleStartTimer:(POMStartTimerIntent *)intent completion:(void (^)(POMStartTimerIntentResponse * _Nonnull))completion
{
    POMStartTimerIntentResponseCode responseCode = POMStartTimerIntentResponseCodeContinueInApp;
    NSUserActivity *userActivity = [self continueIntentInAppUserActivity];

    POMStartTimerIntentResponse *response = [[POMStartTimerIntentResponse alloc] initWithCode:responseCode userActivity:userActivity];

    completion(response);
}

// There seems to be a bug in watchOS which results in the extension delegate's handleActivity: method being called twice when an intent is continued in the app. Passing along a timestamp allows the app to check if it should respond (it remembers the timestamp of the previous intent and ignores a duplicate)
- (NSUserActivity *)continueIntentInAppUserActivity
{
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:@"com.hacknicity.******.continue-intent-in-app"];

    NSTimeInterval timestamp = [[NSDate date] timeIntervalSinceReferenceDate];
    NSString *timestampString = [NSString stringWithFormat:@"%.6f", timestamp];

    [userActivity addUserInfoEntriesFromDictionary:@{@"timestamp" : timestampString}];

    return userActivity;
}



In the Watch app's handler for the interaction I check the timestamp to see if it's the same as the last one I saw. If so, it's a duplicate and I ignore it. If not, I perform the action and remember the timestamp for next time.