carekit-apple/CareKit

Completion Rings Not Filling

YashveerR opened this issue · 2 comments

Creating an app that utilises ResearchKit surveys and CareKit. As per the guide on the start page, I have managed to successfully integrate the two. Running into a little issue now and not sure where to look, as the title suggests, upon completing a survey (of which there are 2), the completion rings do not fill out.

I would like to know what are the possible reasons for this and where would I start to look ?

Including the snippet of the survey presentation and storing of result ( in the Subclassed view controller as the guide suggests):

// 2. This method is called when the use taps the button!
     override func taskView(_ taskView: UIView & OCKTaskDisplayable, didCompleteEvent isComplete: Bool, at indexPath: IndexPath, sender: Any?) {
        
        // 2a. If the task was uncompleted, fall back on the super class's default behavior or deleting the outcome.
        if !isComplete {
            super.taskView(taskView, didCompleteEvent: isComplete, at: indexPath, sender: sender)
            return
        }
        //we need to check the dates here somehow and disable the card from being edited if not today... 
        // 2b. If the user attemped to mark the task complete, display a ResearchKit survey.
        let answerFormat = ORKAnswerFormat.scale(withMaximumValue: 10, minimumValue: 1, defaultValue: 5, step: 1, vertical: false, maximumValueDescription: "Very painful", minimumValueDescription: "No pain")
        let painStep = ORKQuestionStep(identifier: "pain", title: "Daily Survey", question: "Rate your pain", answer: answerFormat)
        let surveyTask = ORKOrderedTask(identifier: "survey", steps: [painStep])
        let surveyViewController = ORKTaskViewController(task: surveyTask, taskRun: nil)
        surveyViewController.delegate = self
        
        surveyViewController.navigationBar.backgroundColor = UIColor.lightGray

         
        
        present(surveyViewController, animated: true, completion: nil)
    }
    
    // 3. This method will be called when the user completes the survey.
    // Extract the result and save it to CareKit's store!
    func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskViewControllerFinishReason, error: Error?) {
        Logger.store.info("Result from survey reason \(String(describing: reason))")
        taskViewController.dismiss(animated: true, completion: nil)
        Logger.store.info("Task is done now, awaiting result")
        guard reason == .completed else {
            taskView.completionButton.isSelected = false
            return
        }
        
        // 4a. Retrieve the result from the ResearchKit survey
        let survey = taskViewController.result.results!.first(where: { $0.identifier == "pain" }) as! ORKStepResult
        let painResult = survey.results?.first as? ORKScaleQuestionResult
        guard let res = painResult?.scaleAnswer else {return}
        let answer = Int(truncating: res)
        Logger.store.info("Task value \(answer)")
        
        // 4b. Save the result into CareKit's store
        controller.appendOutcomeValue(value: answer, at: IndexPath(item: 0, section: 0), completion: nil)
    }

I have stepped through the storing of result which does so correctly and there are no errors displayed on the console.

For the initial loading of the tasks for the day (it successfully gets the 2 tasks for the days)

    override func dailyPageViewController(
        _ dailyPageViewController: OCKDailyPageViewController,
        prepare listViewController: OCKListViewController,
        for date: Date) {
            
            let isFuture = Calendar.current.compare(
                            date,
                            to: Date(),
                            toGranularity: .day) == .orderedDescending
            
            self.fetchTasks(on: date) { tasks in
                            tasks.compactMap {

                                let card = self.taskViewController(for: $0, on: date)
                                card?.view.isUserInteractionEnabled = !isFuture
                                card?.view.alpha = isFuture ? 0.4 : 1.0
                                
                                let today = Calendar.current.startOfDay(for: Date())
                                
                                if (date < today){
                                    card?.view.isUserInteractionEnabled = false
                                    card?.view.alpha = 0.4
                                }

                                return card

                            }.forEach {
                                listViewController.appendViewController($0, animated: false)
                            }
                        }
        }
            
    func fetchTasks(
       on date: Date,
       completion: @escaping([OCKAnyTask]) -> Void) {

       var query = OCKTaskQuery(for: date)
       query.excludesTasksWithNoEvents = true

           storeManager.store.fetchAnyTasks(
               query: query,
               callbackQueue: .main) { result in

               switch result {

               case .failure:
                   Logger.feed.error("Failed to fetch tasks for date \(date)")
                   completion([])

               case let .success(tasks):
                   Logger.feed.error("Successfully fetched tasks for this date:  \(date)")
                   completion(tasks)
               }
           }
       }

Would like to know if I am missing something somewhere, or just any direction really.

Thanks

Hey @YashveerR, thanks for posting some snippets of code. I'm not immediately seeing the cause of the issue. Have you considered using the OCKSurveyTaskViewController? That handles a lot of the boilerplate required for connecting RK and CK, and may iron out some issues.

I'm going to withdraw this one, there perhaps is an issue with the store or how I am using the store. Using the CardinalKit library and the same code as above, the rings fill out. I will re-review how I use the sync store, maybe it will point me in the right direction. If I do have further problems will paste the further sections of code to this one.