Researchkit:如何从 UIWebView 手动切换到下一步
Researchkit: How to switch to next step manually out of UIWebView
我想实现我自己的 ResearchKit 步骤,包括一个 WebView,其中一个按钮可以切换到下一步。
是否可以
1) 手动启动切换到下一步?
2) 操纵结果,从我的 WebView 接收一些数据?
出于学习目的,到目前为止我创建了以下内容,包括我自己的 ActiveStep:
import UIKit
import ResearchKit
class DemoView: UIWebView {
}
class DemoStepViewController : ORKActiveStepViewController {
override func viewDidLoad() {
super.viewDidLoad()
let demoView = UIWebView()
demoView.loadHTMLString("<html><body><p>Hello!</p></body></html>", baseURL: nil)
demoView.translatesAutoresizingMaskIntoConstraints = false
self.customView = demoView
self.customView?.superview!.translatesAutoresizingMaskIntoConstraints = false
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[demoView]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["demoView": demoView]))
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[demoView]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["demoView": demoView]))
}
}
class DemoStep : ORKActiveStep {
static func stepViewControllerClass() -> DemoStepViewController.Type {
return DemoStepViewController.self
}
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, ORKTaskViewControllerDelegate {
var window: UIWindow?
var taskResultFinishedCompletionHandler: (ORKResult -> Void)?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let activeStep = DemoStep(identifier: "webstep")
activeStep.title = "Demo Step"
var endStep = ORKCompletionStep(identifier: "endstep")
endStep.title = "Well done"
endStep.text = "thank you"
let task = ORKOrderedTask(identifier: "orderedtask", steps: [activeStep, endStep])
let taskViewController = ORKTaskViewController(task: task, taskRunUUID: nil)
taskViewController.delegate = self
taskViewController.outputDirectory = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String, isDirectory: true)
window?.rootViewController = taskViewController
return true
}
func taskViewController(taskViewController: ORKTaskViewController, didFinishWithReason reason: ORKTaskViewControllerFinishReason, error: NSError?) {
taskResultFinishedCompletionHandler?(taskViewController.result)
taskViewController.dismissViewControllerAnimated(true, completion: nil)
}
}
我是这样解决问题的:
1) 使用从 javascript 接收结果的 WKWebView 脚本消息处理程序。一旦消息处理程序收到结果,它就会启动 ActiveTask 的计时器,该计时器被设置为一个非常小的值。
你可以在这里看到我的实现作为对另一个 Whosebug 问题的回答:
Creating custom ORKStep with WKWebView
2) 要将步骤结果包含到任务中,我只需在我的步骤视图控制器中覆盖结果 属性。
var JS_Answer = ORKTextQuestionResult()
override var result : ORKStepResult? {
let step_Result = super.result!
step_Result.results = [JS_Answer] // result will look up the answer here
return step_Result
}
// Handle the message posted by Javascript
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
if let widget_Result = message.body as? String {
JS_Answer.identifier = step!.identifier
// write the answer from WebView to JS_Answer, which will be accessed by result
JS_Answer.textAnswer = widget_Result
start()
}
}
我想实现我自己的 ResearchKit 步骤,包括一个 WebView,其中一个按钮可以切换到下一步。
是否可以
1) 手动启动切换到下一步?
2) 操纵结果,从我的 WebView 接收一些数据?
出于学习目的,到目前为止我创建了以下内容,包括我自己的 ActiveStep:
import UIKit
import ResearchKit
class DemoView: UIWebView {
}
class DemoStepViewController : ORKActiveStepViewController {
override func viewDidLoad() {
super.viewDidLoad()
let demoView = UIWebView()
demoView.loadHTMLString("<html><body><p>Hello!</p></body></html>", baseURL: nil)
demoView.translatesAutoresizingMaskIntoConstraints = false
self.customView = demoView
self.customView?.superview!.translatesAutoresizingMaskIntoConstraints = false
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[demoView]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["demoView": demoView]))
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[demoView]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["demoView": demoView]))
}
}
class DemoStep : ORKActiveStep {
static func stepViewControllerClass() -> DemoStepViewController.Type {
return DemoStepViewController.self
}
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, ORKTaskViewControllerDelegate {
var window: UIWindow?
var taskResultFinishedCompletionHandler: (ORKResult -> Void)?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let activeStep = DemoStep(identifier: "webstep")
activeStep.title = "Demo Step"
var endStep = ORKCompletionStep(identifier: "endstep")
endStep.title = "Well done"
endStep.text = "thank you"
let task = ORKOrderedTask(identifier: "orderedtask", steps: [activeStep, endStep])
let taskViewController = ORKTaskViewController(task: task, taskRunUUID: nil)
taskViewController.delegate = self
taskViewController.outputDirectory = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String, isDirectory: true)
window?.rootViewController = taskViewController
return true
}
func taskViewController(taskViewController: ORKTaskViewController, didFinishWithReason reason: ORKTaskViewControllerFinishReason, error: NSError?) {
taskResultFinishedCompletionHandler?(taskViewController.result)
taskViewController.dismissViewControllerAnimated(true, completion: nil)
}
}
我是这样解决问题的:
1) 使用从 javascript 接收结果的 WKWebView 脚本消息处理程序。一旦消息处理程序收到结果,它就会启动 ActiveTask 的计时器,该计时器被设置为一个非常小的值。
你可以在这里看到我的实现作为对另一个 Whosebug 问题的回答: Creating custom ORKStep with WKWebView
2) 要将步骤结果包含到任务中,我只需在我的步骤视图控制器中覆盖结果 属性。
var JS_Answer = ORKTextQuestionResult()
override var result : ORKStepResult? {
let step_Result = super.result!
step_Result.results = [JS_Answer] // result will look up the answer here
return step_Result
}
// Handle the message posted by Javascript
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
if let widget_Result = message.body as? String {
JS_Answer.identifier = step!.identifier
// write the answer from WebView to JS_Answer, which will be accessed by result
JS_Answer.textAnswer = widget_Result
start()
}
}