Search code examples
iosiphoneswiftnspredicateresearchkit

ios swift ResearchKit condition for skip with NSPredicate


I am working on a small app using ResearchKit. Unfortunately I could not find enough examples to figure out how to skip a question based on the answer from a previous question. I have put together the below code, which I know is not ok and not working. I am looking for help to figure out what is not ok.

let textChoices2 = [

ORKTextChoice(text: "Answer 1", value: 0),

ORKTextChoice(text: "Answer 2", value: 1),

ORKTextChoice(text: "Answer 3", value: 2),

ORKTextChoice(text: "Answer 4", value: 3)
]

let questAnswerFormat2: ORKTextChoiceAnswerFormat = ORKAnswerFormat.choiceAnswerFormatWithStyle(.SingleChoice, textChoices: textChoices2)

let questQuestionStep2 = ORKQuestionStep(identifier: "TextChoiceQuestionStep2", title: questQuestionStepTitle, answer: questAnswerFormat2)

//////////////////////////// Here I need help

let task: ORKNavigableOrderedTask = ORKNavigableOrderedTask(identifier: "xyz123", steps: steps)

//the identifier for ORKNavigableOrderedTask is a random number in my case, is it ok like this?

let resultSelector: ORKResultSelector = ORKResultSelector(stepIdentifier: "TextChoiceQuestionStep", resultIdentifier: "ImageChoiceQuestionStep”)

//stepIdentifier is the question based on which I decide if I want to skip the current question. Is it ok like this?

//resultIdentifier is the question to which I want to jump to. Is it ok like this?

let predicate: NSPredicate = ORKResultPredicate.predicateForChoiceQuestionResultWithResultSelector(resultSelector, expectedAnswerValue: "0”)

//expectedAnswerValue is the value of the answer for which I want to skip the current question. Is it ok like this?

let predicateRule: ORKPredicateStepNavigationRule = ORKPredicateStepNavigationRule(resultPredicatesAndDestinationStepIdentifiers:[ (predicate, "ImageChoiceQuestionStep") ])

//“ImageChoiceQuestionStep” from the row above is the question to which I want to jump to. Is it ok like this?

task.setNavigationRule(predicateRule, forTriggerStepIdentifier: "ImageChoiceQuestionStep”)

//“ImageChoiceQuestionStep” from the row above is the question to which I want to jump to. Is it ok like this?

questQuestionStep2.task = task

Solution

  • The function of a resultSelector (docs) is to identify the exact result you want the predicate to match against. A resultSelector must have a resultIdentifier, which in question steps is both the identifier of the question step and the question result within (it is not the identifier of the step you want to jump to!).

    Optionally, a resultSelector can have a stepIdentifier (when you want to match form results, several of whom can be contained in the same step) or a taskIdentifier (if you want to match a result in a previously completed task). I think you don't need these two for your use case.

    Then, with a valid resultSelector pointing to your question of interest, you build a result predicate, and with the predicate you build an ORKPredicateStepNavigationRule which will have the destinationStepIdentifier (this is the step you want to jump to).

    Finally, you attach the predicate step navigation rule to the step which must trigger the rule (which can be the same step being matched by the predicate, or a step that appears later in the task).

    Once you have set everything up and you run the task, the navigation rule is triggered when you are leaving the step it is attached to, and the destinationIdentifier contained in the navigation rule points to the step you conditionally jump to.

    See the TaskFactory.swift file (which implements the Navigable Ordered Task item in the ORKTest example project) for a complete example on how to achieve conditional jumps on swift.

    Also check the documentation on ORKNavigableOrderedTask, ORKPredicateStepNavigationRule and ORKResultPredicate for further information.

    I believe you can achieve what you want by using these.


    Additionally, there's an ongoing Pull Request which adds the concept of skip navigation rules to ORKNavigableTask, which may be more specifically suitable to your needs. But I suggest you grasp how the general navigation rules work first. Hopefully that PR will be merged soon.