注意:我在两天前尝试在苹果开发者论坛上发帖,也没有收到任何回复
我一直坚持我的项目的这一部分,因为我想反映苹果为向用户显示任务而设置护理视图的方式。由于某种原因,我无法将“OCKSurveyTaskViewController”子类化,因为我得到的错误是:
“在范围内找不到类型‘OCKSurveyTaskViewController’”
我已经通过 SPM 2 或 3 次重新安装了 CareKit,即使我看到确切的 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