簡體   English   中英

為什么我不能從 CareKit 子類化“OCKSurveyTaskViewController”?

[英]Why can't I subclass 'OCKSurveyTaskViewController' from CareKit?

注意:我兩天前嘗試在蘋果開發者論壇上發帖,也沒有收到任何回復

我一直被困在我項目的這一部分,因為我想反映蘋果為向用戶顯示任務而設置的護理視圖的方式。 由於某種原因,我不能將 'OCKSurveyTaskViewController' 子類化,因為我得到的錯誤是:

“在范圍內找不到類型‘OCKSurveyTaskViewController’”

我已經通過 SPM 重新安裝了 CareKit 2 到 3 次,但我不明白為什么即使我看到確切的 OCKSurveyTaskViewController.swift 文件並且它在代碼中列為 CareKit/iOS 中的開放類,我也無法將其子類化Xcode 中的 /Task/ViewController 目錄。

任何人都可以給我一些指導或另一種方式來以另一種方式顯示我每天為用戶建立的 ORKTasks 嗎? 我更喜歡蘋果在他們的 wwdc21 CareKit 代碼中使用的方法,但可惜我已經堅持這個方法太久了,這是進入下一步所必需的。

這是我的文件代碼:

import UIKit
import CareKit
import CareKitUI
import CareKitStore
import ResearchKit
import os.log

class StudyTaskFeedViewController: OCKDailyTasksPageViewController, OCKSurveyTaskViewController {}

這是 OCKSurveyTaskViewController.swift 文件的代碼:

#if !os(watchOS) && canImport(ResearchKit)

import CareKitStore
import CareKitUI
import ResearchKit
import UIKit

// MARK: OCKSurveyTaskViewControllerDelegate

public protocol OCKSurveyTaskViewControllerDelegate: AnyObject {

    func surveyTask(
        viewController: OCKSurveyTaskViewController,
        for task: OCKAnyTask,
        didFinish result: Result<ORKTaskViewControllerFinishReason, Error>)

    func surveyTask(
        viewController: OCKSurveyTaskViewController,
        shouldAllowDeletingOutcomeForEvent event: OCKAnyEvent) -> Bool
}

public extension OCKSurveyTaskViewControllerDelegate {

    func surveyTask(
        viewController: OCKSurveyTaskViewController,
        for task: OCKAnyTask,
        didFinish result: Result<ORKTaskViewControllerFinishReason, Error>) {
        // No-op
    }

    func surveyTask(
        viewController: OCKSurveyTaskViewController,
        shouldAllowDeletingOutcomeForEvent event: OCKAnyEvent) -> Bool {
        return true
    }
}

open class OCKSurveyTaskViewController: OCKTaskViewController<OCKTaskController, OCKSurveyTaskViewSynchronizer>, ORKTaskViewControllerDelegate {

    private let extractOutcome: (ORKTaskResult) -> [OCKOutcomeValue]?

    public let survey: ORKTask

    public weak var surveyDelegate: OCKSurveyTaskViewControllerDelegate?

    public convenience init(
        task: OCKAnyTask,
        eventQuery: OCKEventQuery,
        storeManager: OCKSynchronizedStoreManager,
        survey: ORKTask,
        viewSynchronizer: OCKSurveyTaskViewSynchronizer = OCKSurveyTaskViewSynchronizer(),
        extractOutcome: @escaping (ORKTaskResult) -> [OCKOutcomeValue]?) {

        self.init(
            taskID: task.id,
            eventQuery: eventQuery,
            storeManager: storeManager,
            survey: survey,
            viewSynchronizer: viewSynchronizer,
            extractOutcome: extractOutcome
        )
    }

    public init(
        taskID: String,
        eventQuery: OCKEventQuery,
        storeManager: OCKSynchronizedStoreManager,
        survey: ORKTask,
        viewSynchronizer: OCKSurveyTaskViewSynchronizer = OCKSurveyTaskViewSynchronizer(),
        extractOutcome: @escaping (ORKTaskResult) -> [OCKOutcomeValue]?) {

        self.survey = survey
        self.extractOutcome = extractOutcome

        super.init(
            viewSynchronizer: viewSynchronizer,
            taskID: taskID,
            eventQuery: eventQuery,
            storeManager: storeManager
        )
    }

    override open func taskView(
        _ taskView: UIView & OCKTaskDisplayable,
        didCompleteEvent isComplete: Bool,
        at indexPath: IndexPath,
        sender: Any?) {

        guard isComplete else {

            if let event = controller.eventFor(indexPath: indexPath),

               let delegate = surveyDelegate,

               delegate.surveyTask(
                    viewController: self,
                    shouldAllowDeletingOutcomeForEvent: event) == false {

                return
            }

            let cancelAction = UIAlertAction(
                title: "Cancel",
                style: .cancel,
                handler: nil
            )

            let confirmAction = UIAlertAction(
                title: "Delete", style: .destructive) { _ in
                
                super.taskView(
                    taskView,
                    didCompleteEvent: isComplete,
                    at: indexPath,
                    sender: sender
                )
            }

            let warningAlert = UIAlertController(
                title: "Delete",
                message: "Are you sure you want to delete your response?",
                preferredStyle: .actionSheet
            )

            warningAlert.addAction(cancelAction)
            warningAlert.addAction(confirmAction)
            present(warningAlert, animated: true, completion: nil)

            return
        }

        let surveyViewController = ORKTaskViewController(
            task: survey,
            taskRun: nil
        )

        let directory = FileManager.default.urls(
            for: .documentDirectory,
            in: .userDomainMask
        ).last!.appendingPathComponent("ResearchKit", isDirectory: true)

        surveyViewController.outputDirectory = directory
        surveyViewController.delegate = self

        present(surveyViewController, animated: true, completion: nil)
    }

    // MARK: ORKTaskViewControllerDelegate
    
    open func taskViewController(
        _ taskViewController: ORKTaskViewController,
        didFinishWith reason: ORKTaskViewControllerFinishReason,
        error: Error?) {

        taskViewController.dismiss(animated: true, completion: nil)

        guard let task = controller.taskEvents.first?.first?.task else {
            assertionFailure("Task controller is missing its task")
            return
        }

        if let error = error {
            surveyDelegate?.surveyTask(
                viewController: self,
                for: task,
                didFinish: .failure(error)
            )
            return
        }

        guard reason == .completed else {
            return
        }

        let indexPath = IndexPath(item: 0, section: 0)

        guard let event = controller.eventFor(indexPath: indexPath) else {
            return
        }

        guard let values = extractOutcome(taskViewController.result) else {
            return
        }

        let outcome = OCKOutcome(
            taskUUID: event.task.uuid,
            taskOccurrenceIndex: event.scheduleEvent.occurrence,
            values: values
        )

        controller.storeManager.store.addAnyOutcome(
            outcome,
            callbackQueue: .main) { result in

            if case let .failure(error) = result {

                self.surveyDelegate?.surveyTask(
                    viewController: self,
                    for: task,
                    didFinish: .failure(error)
                )
            }

            self.surveyDelegate?.surveyTask(
                viewController: self,
                for: task,
                didFinish: .success(reason)
            )
        }
    }
}

#endif

當我嘗試在我自己的應用程序中從“恢復”應用程序復制演示代碼時遇到了同樣的問題。 在將我的項目設置與“Recover”進行比較后,我注意到我沒有在目標應用程序的 Sign&Capabilities 中添加“HealthKit”的功能。 添加此功能后,它起作用了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM