Unable to read disambiguation result in INAddTasksIntent

Published

In my app, users can add tasks to lists via Sirikit (example Siri intent query: “In MyApp add to expense list 100 dollars for jeans”). if the list suggested is not available in the app, I ask for disambiguation.

the result from multiple choice in disambiguation is not captured in resolveTargetTaskList.

intent.targetTaskList?.title is the value I passed in the first try. as a result, it enters an infinite loop.

func resolveTargetTaskList(for intent: INAddTasksIntent, with completion: @escaping (INTaskListResolutionResult) -> Void) {  
    guard let title = intent.targetTaskList?.title else {  
        completion(.needsValue())  
        print("no title value")              
    }  
    completeResolveTaskList(listName: intent.targetTaskList!.title, with: completion)  
}  



public func completeResolveTaskList(listName: INSpeakableString, with completion: @escaping (INTaskListResolutionResult) -> Void) {  
    print("completeResolveTaskList")  
    let allLists = getAllLists()  
    for index in 0...(allLists.count - 1) {  
        if allLists[index].spokenPhrase.lowercased() == listName.spokenPhrase.lowercased() {  
            completion(.success(with: taskLists[index]))  
        }  
    }  

    switch allLists.count {  
    case 0:  
        completion(.unsupported())  
    default:  
        completion(.disambiguation(with: taskLists))  
    }  
}  

screenshot for reference:

screenshot

Please help me.

Source: Ios

Published
Categorised as ios, siri, sirikit, swift

Answers

On second reading I think I see it:

You need to return right after completion(.success(with: taskLists[index])), otherwise you will still execute the rest of the function, which includes a recursive call.

In general I’d advise to modify your function like so:

public func completeResolveTaskList(listName: INSpeakableString, with completion: @escaping (INTaskListResolutionResult) -> Void) {  
    print("completeResolveTaskList")  
    let allLists = getAllLists()
    guard let matching = allLists.first(where: { $0.spokenPhrase.lowercased() == listName.spokenPhrase.lowercased() }) else {
        switch allLists.count {  
        case 0:  
            completion(.unsupported())  
        default:  
            completion(.disambiguation(with: taskLists))  
        }
        return
    }

    completion(.success(with: matching))  
}

This matches, imo, the flow a bit closer and in a more swifty way. Granted, the else for the guard statement is a little longer, but you could always refactor that into another method. In general it’s more like “get me the first element that matches the input. If you don’t find any, do some fallback, otherwise proceed normally”. It also gets rid of iterating over the list with an index.


Shane Streich

Leave a Reply

Your email address will not be published. Required fields are marked *

Still Have Questions?


Our dedicated development team is here for you!

We can help you find answers to your question for as low as 5$.

Contact Us
faq