snailmensch snailmensch - 5 months ago 18
iOS Question

Researchkit: How to switch to next step manually out of UIWebView

I want to implement my own ResearchKit step including a WebView in which a button gives the possibility to switch to the next step.

Is it therefore possible to

1) initiate switching to the next step manually?

2) manipulate the result, receiving some data from my WebView?

For learning purposes I created following so far, including my own 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)
}
}

Answer

I solved the problem like this:

1) Use a WKWebView scriptmessagehandler that receives the result from javascript. As soon as the messagehandler receives a result it starts the ActiveTask's timer which is set to a very small value.

You can see my implementation here as answer to another stackoverflow question: Creating custom ORKStep with WKWebView

2) Because I didn't find a way to manipulate the tasks result or a way to insert additional results, I decided to collect my ActiveStep's results seperately. With completion of the task I merge the results outside the survey. The best time to do that is maybe with the call of taskViewController(taskViewController: ORKTaskViewController, didFinishWithReason reason: ORKTaskViewControllerFinishReason, error: NSError?)