|
2 weeks ago | |
---|---|---|
SAGE_RK_ML | 2 weeks ago | |
images | 2 weeks ago | |
.DS_Store | 2 weeks ago | |
README.md | 2 weeks ago |
README.md
Enhancing Biomedical Research with ResearchKit: Digitization of IPAQ and MMSE for Sedentary Behavior and Cognitive Impairment Analysis
Juan David López-Regalado and Gerardo Marx Chávez-Campos
Medical questionnaires and forms play a crucial role in diagnosing diseases and gathering essential patient information. Traditionally, these assessments are conducted through face-to-face interactions or phone calls, which can be time-consuming, costly, and inefficient. To address these challenges, digital adaptations of medical questionnaires have been developed, enabling faster and more accessible data collection across various platforms and applications.
ResearchKit, an open-source framework introduced by Apple, allows researchers and developers to create robust mobile applications for medical research. By leveraging this technology, large-scale data collection can be conducted efficiently, facilitating real-time analysis while reaching a broader population.
Create project and implementation of ResearchKit
For create a medical applications for digitized questionnaires, it's necessary to download the framework from the next repository
and create a new ios project in Xcode in the option App.
The next window will ask you name, interface, lenguage among other, but it is left as default, we only put a name and identifier, and saved in the desired path.
When the project is create the main window looks like the next image
This is a main window, all the files from the application are found here, this is the environment where you work.
The previous folder download from github contain a xcode file, it name is ResearchKit.xcodeproj this file will be dragged to the top of the Xcode file explorer, as shown in the image below.
When the famework is here, is part of the application, only needs to activate. In the root of the application exist a general configuration, here in Framework, Libraries and Embededden Content in the plus sign is necessary activate the 3 parts of framework, in the next GIF, show how do that.
Doing that, ResearchKit is ready to use.
Visual Interface
The first part for develop a application is the visual part, you need to create a visual interface because the participants need a intuitive screen. This repository is not about the interface part, only about the ResearchKit part, therefore, we will skip the visual part, we can only say that it is necessary to place 3 buttons, one for consent, another for IPAQ and another for MMSE.
In this case needs 3 ViewControllers, each one for activity, it is the most easy form to doing and the code it's more easy too.
The visual interface needs to be easy, intuitive, but the design is part of you.
The main screen should be like the next image:
Now, it is necessary create 3 files for Consent(ConsentViewController, ConsentTask and ConsentDocument), 2 for IPAQ (IPAQViewConstroller and IPAQManager) and 2 for MMSE (MMSEViewController and MMSEManager). Files with termination ViewController are type CocoaTouchClass with subclass UIViewController and other termination only Swift File. In the next GIF show how to create this two files.
With all the files created, should look like the next image:
The files are in charge of managing all the forms that are generated with ResearchKit, the Managers are in charge of saying what and what parts are added to the form, that is, the questions, and the ViewController is in charge of triggering it and displaying it on the cell phone.
In case of Consent it's similar, but it's divide de Manager in two files, the sections and the content.
Develop Consent, IPAQ and MMSE
For develop a consent it's necessary knows the content that you need for your participants, but most of them require the same sections.
In ConsentDocument it is required put the sections that content the consent, and you need to add a code like this:
import Foundation
import ResearchKit
public var ConsentDocument: ORKConsentDocument {
let consentDocument = ORKConsentDocument()
consentDocument.title = "Conset for questionaires IPAQ and MMSE" // Title
// Type of sections
let sectionTypes: [ORKConsentSectionType] = [
.overview,
.dataGathering,
.privacy,
.dataUse,
.timeCommitment,
.studySurvey,
.studyTasks,
.withdrawing
]
let text = [
"Section 1: Welcome. This study is about...",
"Section 2: Data Gathering. This study will collect data from your Apple Watch...",
"Section 3: Privacy. We value your privacy...",
"Section 4: Data Use. The data collected will be used for...",
"Section 5: Time Commitment. This study will take you roughly...",
"Section 6: Study Survey. For this study, you will need to fill out a survey...",
"Section 7: Study Tasks. You will be requested to do these tasks...",
"Section 8: Withdrawing. To withdraw from the study..."
]
// Create sections and add them to the consent document
var sections: [ORKConsentSection] = []
for (index, sectionType) in sectionTypes.enumerated() {
let section = ORKConsentSection(type: sectionType)
let localizedText = NSLocalizedString(text[index], comment: "")
let localizedSummary = localizedText.components(separatedBy: ".")[0] + "."
section.summary = localizedSummary
section.content = localizedText
sections.append(section)
}
consentDocument.sections = sections
// add sign to consent
let signature = ORKConsentSignature(forPersonWithTitle: "Participante", dateFormatString: nil, identifier: "ConsentDocumentParticipantSignature")
consentDocument.addSignature(signature)
return consentDocument
}
This code define sections such as privacy, data collection and use, time commitment, and withdrawal from the study, assigning explanatory texts to each. Additionally, add a field for the participant to sign, ensuring that the consent is complete and ready to be used in the app.
And now the sequence of how it will be shown is putted in the file ConsentTask like the next code:
import UIKit
import ResearchKit
public var ConsentTask: ORKOrderedTask {
var steps = [ORKStep]()
// Visualization of sections
let consentDocument = ConsentDocument
// Section 1: Welcome
let section1 = ORKInstructionStep(identifier: "consentSection1InstructionStep")
section1.title = "Welcome"
section1.iconImage = UIImage(systemName: "hand.wave")
section1.detailText = "Section 1: Welcome. This study is about..."
steps += [section1]
// Section 2: Data Collection
let section2 = ORKInstructionStep(identifier: "consentSection2InstructionStep")
section2.title = "Data Collection"
section2.iconImage = UIImage(systemName: "doc.text")
section2.detailText = "Section 2: Data Collection. This study will collect data..."
steps += [section2]
// Section 3: Privacy
let section3 = ORKInstructionStep(identifier: "consentSection3InstructionStep")
section3.title = "Privacy"
section3.iconImage = UIImage(systemName: "lock.shield")
section3.detailText = "Section 3: Privacy. We value your privacy..."
steps += [section3]
// Section 4: Data Use
let section4 = ORKInstructionStep(identifier: "consentSection4InstructionStep")
section4.title = "Data Use"
section4.iconImage = UIImage(systemName: "chart.bar")
section4.detailText = "Section 4: Data Use. The collected data will be used for..."
steps += [section4]
// Section 5: Time Commitment
let section5 = ORKInstructionStep(identifier: "consentSection5InstructionStep")
section5.title = "Time Commitment"
section5.iconImage = UIImage(systemName: "clock")
section5.detailText = "Section 5: Time Commitment. This study will take approximately..."
steps += [section5]
// Section 6: Study Survey
let section6 = ORKInstructionStep(identifier: "consentSection6InstructionStep")
section6.title = "Study Survey"
section6.iconImage = UIImage(systemName: "list.bullet.rectangle")
section6.detailText = "Section 6: Study Survey. For this study, you will need to complete a survey..."
steps += [section6]
// Section 7: Study Tasks
let section7 = ORKInstructionStep(identifier: "consentSection7InstructionStep")
section7.title = "Study Tasks"
section7.iconImage = UIImage(systemName: "pencil.and.outline")
section7.detailText = "Section 7: Study Tasks. You will be required to perform these tasks..."
steps += [section7]
// Section 8: Withdrawal
let section8 = ORKInstructionStep(identifier: "consentSection8InstructionStep")
section8.title = "Withdrawal"
section8.iconImage = UIImage(systemName: "arrow.backward.circle")
section8.detailText = "Section 8: Withdrawal. To withdraw from the study..."
steps += [section8]
// Review and Sign
let signature = consentDocument.signatures!.first!
let reviewConsentStep = ORKConsentReviewStep(identifier: "ConsentReviewStep", signature: signature, in: consentDocument)
reviewConsentStep.title = "Review"
reviewConsentStep.text = "Review the consent form."
reviewConsentStep.reasonForConsent = "Consent to join the study"
steps += [reviewConsentStep]
// Passcode/TouchID Protection
let passcodeStep = ORKPasscodeStep(identifier: "Passcode")
passcodeStep.iconImage = UIImage(systemName: "lock.circle")
passcodeStep.text = "You will now create a passcode to identify yourself in the app and protect the entered information."
steps += [passcodeStep]
// Completion
let completionStep = ORKCompletionStep(identifier: "CompletionStep")
completionStep.iconImage = UIImage(systemName: "checkmark.seal")
completionStep.title = "Welcome aboard"
completionStep.text = "Thank you for joining this study."
steps += [completionStep]
return ORKOrderedTask(identifier: "ConsentTask", steps: steps)
}
This code explain each section, the sequence and the contet shown in the application.
Now is necessary program the trigger, it means the button that show the consent.The button of consent is programmed in ConsentViewController, need to open the consent en the interface, for to drag the button to the controller and give it the action function, adding the code where it tells us that when pressing the button, the consent is displayed.
The following GIF shows how the drag would be done and the code will be placed below.
import UIKit
import ResearchKit
import ResearchKitUI
class ConsentViewController: UIViewController, ORKTaskViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.hidesBackButton = false
// Do any additional setup after loading the view.
}
@IBAction func consentButton(_ sender: UIButton) {
let taskViewController = ORKTaskViewController(task: ConsentTask, taskRun: nil)
taskViewController.delegate = self
taskViewController.modalPresentationStyle = .fullScreen
present(taskViewController, animated: true, completion: nil)
}
func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskFinishReason, error: (any Error)?) {
if let error = error {
print("Error en ResearchKit: \(error.localizedDescription)")
}
taskViewController.dismiss(animated: true, completion: nil)
}
}
It's necessary put all the code, because it add a ORKTaskViewCOntroller and a "if" in errors.
If you push the button, the consent will be open.
Its time for IPAQ and MMSE, These questionnaires, as mentioned in the article, will be digitized so that they can be answered on Apple mobile devices. The first thing to do is to know the different questions that the questionnaire contains in order to digitize it in the many functions that ResearchKit has incorporated. In this case, ORKValuePickerAnswerFormat, ORKTextAnswerFormat, ORKNumericAnswerFormat, ORKTextChoiceAnswerFormat, and ORKScaleAnswerFormat are used.
For doing a digital questions it is necessary to check the type of physical question, for example:
IPAQ have 7 Questions and 5 espaces for only read (sentences), so the first part is the title, the title says: "INTERNATIONAL PHYSICAL ACTIVITY QUESTIONNAIRE (IPAQ)", its only a sentence so in xcode need the function ORKInstructionStep as see:
// Define the introduction step
let ipaqInfo = ORKInstructionStep(identifier: "IPAQInfo")
ipaqInfo.title = "IPAQ Test"
ipaqInfo.iconImage = UIImage(systemName: "figure.run")
ipaqInfo.detailText = "International Physical Activity Questionnaire\n\nWe will ask you 7 questions related to your physical activity. Please answer as honestly as possible."
This function have one identifier, a title, one iconImage and a detailText, so the sentence looks like.
you can omit one part, but with all the features it's more complete, and for all the sentences it's the same, for both questionnaires.
Now, for questions, let's see the question one of IPAQ, it said: "1. During the last 7 days, on how many days did you do vigorous physical activities like heavy lifting, digging, aerobics, or fast bicycling?", so the firt step is decide in one window all the questions or one for window, in this case it is one for window, so the main function it is ORKQuestionStep, and now, what type of answer exist various types, like picker, text, text choices, scale, among others, it depends our question, for this case, is picker, so the function should be like:
let vigorousDaysChoices = [
ORKTextChoice(text: "None", value: "None" as NSString),
ORKTextChoice(text: "1 day", value: "1 day" as NSString),
ORKTextChoice(text: "2 days", value: "2 days" as NSString),
ORKTextChoice(text: "3 days", value: "3 days" as NSString),
ORKTextChoice(text: "4 days", value: "4 days" as NSString),
ORKTextChoice(text: "5 days", value: "5 days" as NSString),
ORKTextChoice(text: "6 days", value: "6 days" as NSString),
ORKTextChoice(text: "7 days", value: "7 days" as NSString)
]
let vigorousDaysStep = ORKQuestionStep(
identifier: "VigorousDays",
title: "Question 1",
question: "In the last 7 days, how many days did you perform vigorous physical activities such as heavy lifting, digging, aerobics, or fast cycling?",
answer: ORKValuePickerAnswerFormat(textChoices: vigorousDaysChoices)
)
the first part is the choices as the participant need to see, second part is the identifier, title, the question and the type of answer, and this type of question its the semae only change the choices.
Other type of questions is Numeric, Text, scale, but each one have its structure, but follow kind of the same for to declarate.
The next image show different types of questions in MMSE, numeric, scale, image, etc.
For doing a IPAQ, as metioned before we need 7 questions and 5 sentences, so the code, is like:
import Foundation
import ResearchKit
class IPAQManager {
static let shared = IPAQManager()
func createIPAQ() -> ORKTask {
// Define the introduction step
let ipaqInfo = ORKInstructionStep(identifier: "IPAQInfo")
ipaqInfo.title = "IPAQ Test"
ipaqInfo.iconImage = UIImage(systemName: "figure.run")
ipaqInfo.detailText = "International Physical Activity Questionnaire\n\nWe will ask you 7 questions related to your physical activity. Please answer as honestly as possible."
// Section 1: Vigorous Activities
let sec1 = ORKInstructionStep(identifier: "Sec1")
sec1.title = "Section 1"
sec1.detailText = "Think about all the VIGOROUS activities you did in the last 7 days. Vigorous physical activities are those that require intense physical effort and make you breathe much harder than usual. Consider only those activities that lasted at least 10 consecutive minutes."
let vigorousDaysChoices = [
ORKTextChoice(text: "None", value: "None" as NSString),
ORKTextChoice(text: "1 day", value: "1 day" as NSString),
ORKTextChoice(text: "2 days", value: "2 days" as NSString),
ORKTextChoice(text: "3 days", value: "3 days" as NSString),
ORKTextChoice(text: "4 days", value: "4 days" as NSString),
ORKTextChoice(text: "5 days", value: "5 days" as NSString),
ORKTextChoice(text: "6 days", value: "6 days" as NSString),
ORKTextChoice(text: "7 days", value: "7 days" as NSString)
]
let vigorousDaysStep = ORKQuestionStep(
identifier: "VigorousDays",
title: "Question 1",
question: "In the last 7 days, how many days did you perform vigorous physical activities such as heavy lifting, digging, aerobics, or fast cycling?",
answer: ORKValuePickerAnswerFormat(textChoices: vigorousDaysChoices)
)
vigorousDaysStep.isOptional = false
let vigorousMinutesStep = ORKQuestionStep(
identifier: "VigorousMinutes",
title: "Question 2",
question: "On those days, how much time (in minutes) did you usually spend performing vigorous physical activities?",
answer: ORKNumericAnswerFormat(style: .integer, unit: "minutes", minimum: 0, maximum: 1440)
)
vigorousMinutesStep.isOptional = false
// Section 2: Moderate Activities
let sec2 = ORKInstructionStep(identifier: "Sec2")
sec2.title = "Section 2"
sec2.detailText = "Think about all the MODERATE activities you did in the last 7 days. Moderate activities require moderate physical effort and make you breathe somewhat harder than usual. Consider only those activities that lasted at least 10 consecutive minutes."
let moderateDaysChoices = [
ORKTextChoice(text: "None", value: "None" as NSString),
ORKTextChoice(text: "1 day", value: "1 day" as NSString),
ORKTextChoice(text: "2 days", value: "2 days" as NSString),
ORKTextChoice(text: "3 days", value: "3 days" as NSString),
ORKTextChoice(text: "4 days", value: "4 days" as NSString),
ORKTextChoice(text: "5 days", value: "5 days" as NSString),
ORKTextChoice(text: "6 days", value: "6 days" as NSString),
ORKTextChoice(text: "7 days", value: "7 days" as NSString)
]
let moderateDaysStep = ORKQuestionStep(
identifier: "ModerateDays",
title: "Question 3",
question: "In the last 7 days, how many days did you perform moderate physical activities such as carrying light loads, cycling at a regular pace, or playing doubles tennis? Do not include walking.",
answer: ORKValuePickerAnswerFormat(textChoices: moderateDaysChoices)
)
moderateDaysStep.isOptional = false
let moderateMinutesStep = ORKQuestionStep(
identifier: "ModerateMinutes",
title: "Question 4",
question: "On those days, how much time (in minutes) did you usually spend performing moderate physical activities?",
answer: ORKNumericAnswerFormat(style: .integer, unit: "minutes", minimum: 0, maximum: 1440)
)
moderateMinutesStep.isOptional = false
// Section 3: Walking
let sec3 = ORKInstructionStep(identifier: "Sec3")
sec3.title = "Section 3"
sec3.detailText = "Think about the time you spent WALKING in the last 7 days. This includes walking at work or home, walking to travel from place to place, or any other walking you might do solely for recreation, sport, exercise, or leisure."
let walkingDaysChoices = [
ORKTextChoice(text: "None", value: "None" as NSString),
ORKTextChoice(text: "1 day", value: "1 day" as NSString),
ORKTextChoice(text: "2 days", value: "2 days" as NSString),
ORKTextChoice(text: "3 days", value: "3 days" as NSString),
ORKTextChoice(text: "4 days", value: "4 days" as NSString),
ORKTextChoice(text: "5 days", value: "5 days" as NSString),
ORKTextChoice(text: "6 days", value: "6 days" as NSString),
ORKTextChoice(text: "7 days", value: "7 days" as NSString)
]
let walkingDaysStep = ORKQuestionStep(
identifier: "WalkingDays",
title: "Question 5",
question: "In the last 7 days, how many days did you walk for at least 10 consecutive minutes?",
answer: ORKValuePickerAnswerFormat(textChoices: walkingDaysChoices)
)
walkingDaysStep.isOptional = false
let walkingMinutesStep = ORKQuestionStep(
identifier: "WalkingMinutes",
title: "Question 6",
question: "On those days, how much time (in minutes) did you usually spend walking?",
answer: ORKNumericAnswerFormat(style: .integer, unit: "minutes", minimum: 0, maximum: 1440)
)
walkingMinutesStep.isOptional = false
// Section 4: Sitting
let sec4 = ORKInstructionStep(identifier: "Sec4")
sec4.title = "Section 4"
sec4.detailText = "The last question is about the time you spent SITTING during the weekdays of the last 7 days. This includes time spent at work, at home, while studying, and during leisure time. It includes time spent sitting at a desk, visiting friends, reading, traveling by car, bus, train, or watching television."
let sittingStep = ORKQuestionStep(
identifier: "SittingTime",
title: "Question 7",
question: "On a typical weekday, how much time (in minutes) did you spend sitting?",
answer: ORKNumericAnswerFormat(style: .integer, unit: "minutes", minimum: 0, maximum: 1440)
)
sittingStep.isOptional = false
// Completion Step
let completionStep = ORKCompletionStep(identifier: "IPAQCompletion")
completionStep.title = "Thank you!"
completionStep.iconImage = UIImage(systemName: "checkmark.seal")
completionStep.text = "You have completed the IPAQ Test. Thank you for your participation!"
// Retorna la tarea combinando los pasos
return ORKOrderedTask(identifier: "SurveyTask", steps: [ipaqInfo,
sec1, vigorousDaysStep, vigorousMinutesStep,
sec2, moderateDaysStep, moderateMinutesStep,
sec3, walkingDaysStep, walkingMinutesStep,
sec4, sittingStep,
completionStep])
}
}
The return its the form to show the questions, the order.
And for MMSE, its too large, because count with 33 questions and 8 sentences, and with different styles, so the code is like this:
import Foundation
import ResearchKit
import ResearchKitUI
class MMSEManager {
static let shared = MMSEManager()
func createMMSE() -> ORKTask {
// Define questionnaire steps
let mmseInfo = ORKInstructionStep(identifier: "MMSEInfo")
mmseInfo.title = "MMSE Test"
mmseInfo.iconImage = UIImage(systemName: "brain.head.profile")
mmseInfo.detailText = "Mini-Mental State Examination\n\nWe will ask you some questions related to your cognition. Please answer as honestly as possible."
// Section 1
let sec1 = ORKInstructionStep(identifier: "Sec1")
sec1.title = "Orientation in Time and Space"
sec1.detailText = "Without checking anything on your phone or any other device, please answer the following questions."
// Question 1
let MMSE1choices = [
ORKTextChoice(text: "Monday", value: "Monday" as NSString),
ORKTextChoice(text: "Tuesday", value: "Tuesday" as NSString),
ORKTextChoice(text: "Wednesday", value: "Wednesday" as NSString),
ORKTextChoice(text: "Thursday", value: "Thursday" as NSString),
ORKTextChoice(text: "Friday", value: "Friday" as NSString),
ORKTextChoice(text: "Saturday", value: "Saturday" as NSString),
ORKTextChoice(text: "Sunday", value: "Sunday" as NSString),
ORKTextChoice(text: "I don’t know", value: "I don’t know" as NSString)
]
let MMSE1QuestionStep = ORKQuestionStep(
identifier: "01DayOfWeek",
title: "Question 1",
question: "What day of the week is today?",
answer: ORKValuePickerAnswerFormat(textChoices: MMSE1choices)
)
MMSE1QuestionStep.isOptional = false
// Question 2
let MMSE2choices = (2000...2030).map { year in
ORKTextChoice(text: "\(year)", value: "\(year)" as NSString)
}
let MMSE2QuestionStep = ORKQuestionStep(
identifier: "02Year",
title: "Question 2",
question: "What year is it?",
answer: ORKValuePickerAnswerFormat(textChoices: MMSE2choices)
)
MMSE2QuestionStep.isOptional = false
// Question 3
let MMSE3choices = [
ORKTextChoice(text: "January", value: "January" as NSString),
ORKTextChoice(text: "February", value: "February" as NSString),
ORKTextChoice(text: "March", value: "March" as NSString),
ORKTextChoice(text: "April", value: "April" as NSString),
ORKTextChoice(text: "May", value: "May" as NSString),
ORKTextChoice(text: "June", value: "June" as NSString),
ORKTextChoice(text: "July", value: "July" as NSString),
ORKTextChoice(text: "August", value: "August" as NSString),
ORKTextChoice(text: "September", value: "September" as NSString),
ORKTextChoice(text: "October", value: "October" as NSString),
ORKTextChoice(text: "November", value: "November" as NSString),
ORKTextChoice(text: "December", value: "December" as NSString)
]
let MMSE3QuestionStep = ORKQuestionStep(
identifier: "03Month",
title: "Question 3",
question: "What month is it?",
answer: ORKValuePickerAnswerFormat(textChoices: MMSE3choices)
)
MMSE3QuestionStep.isOptional = false
// Question 4
let MMSE4choices = (1...31).map { day in
ORKTextChoice(text: "\(day)", value: "\(day)" as NSString)
}
let MMSE4QuestionStep = ORKQuestionStep(
identifier: "04DayOfMonth",
title: "Question 4",
question: "What is today’s date?",
answer: ORKValuePickerAnswerFormat(textChoices: MMSE4choices)
)
MMSE4QuestionStep.isOptional = false
// Question 5
let MMSE5AnswerFormat = ORKTextAnswerFormat(maximumLength: 50)
MMSE5AnswerFormat.multipleLines = false
let MMSE5QuestionStep = ORKQuestionStep(
identifier: "05Time",
title: "Question 5",
question: "What time is it approximately? (e.g., 3:00 PM, 14:00, 4:30 PM, 19:45)",
answer: MMSE5AnswerFormat
)
MMSE5QuestionStep.isOptional = false
// Question 6
let MMSE6choices = [
ORKTextChoice(text: "Spring", value: "Spring" as NSString),
ORKTextChoice(text: "Summer", value: "Summer" as NSString),
ORKTextChoice(text: "Autumn", value: "Autumn" as NSString),
ORKTextChoice(text: "Winter", value: "Winter" as NSString)
]
let MMSE6QuestionStep = ORKQuestionStep(
identifier: "06Season",
title: "Question 6",
question: "What season are we in?",
answer: ORKValuePickerAnswerFormat(textChoices: MMSE6choices)
)
MMSE6QuestionStep.isOptional = false
// Question 7
let MMSE7AnswerFormat = ORKTextAnswerFormat(maximumLength: 50)
MMSE7AnswerFormat.multipleLines = true
let MMSE7QuestionStep = ORKQuestionStep(
identifier: "07Location",
title: "Question 7",
question: "Where are you right now? (e.g., Home, Work, Park, School)",
answer: MMSE7AnswerFormat
)
MMSE7QuestionStep.isOptional = false
// Question 8
let MMSE8AnswerFormat = ORKTextAnswerFormat(maximumLength: 50)
MMSE8AnswerFormat.multipleLines = true
let MMSE8QuestionStep = ORKQuestionStep(
identifier: "08City",
title: "Question 8",
question: "What city are you in?",
answer: MMSE8AnswerFormat
)
MMSE8QuestionStep.isOptional = false
// Question 9
let MMSE9AnswerFormat = ORKTextAnswerFormat(maximumLength: 50)
MMSE9AnswerFormat.multipleLines = true
let MMSE9QuestionStep = ORKQuestionStep(
identifier: "09State",
title: "Question 9",
question: "What state are you in?",
answer: MMSE9AnswerFormat
)
MMSE9QuestionStep.isOptional = false
// Question 10
let MMSE10QuestionStepTitle = "Question 10"
let MMSE10AnswerFormat = ORKTextAnswerFormat(maximumLength: 50)
MMSE10AnswerFormat.multipleLines = true
let MMSE10QuestionStep = ORKQuestionStep(identifier: "10Country", title: MMSE10QuestionStepTitle, question: "Which country are you in?", answer: MMSE10AnswerFormat)
MMSE10QuestionStep.isOptional = false
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Section 2
let sec2 = ORKInstructionStep(identifier: "Sec2")
sec2.title = "Fixation"
sec2.detailText = "Without reviewing anything on your phone or any other device, answer the following questions"
// Question 11
let words1 = ORKInstructionStep(identifier: "words1")
words1.title = "Reading"
words1.detailText = "Read the following 3 words and click the (Next) button \n\nHORSE\n\nWEIGHT\n\nAPPLE"
// Word 1
let MMSE11QuestionStepTitle1 = "Question 11"
let MMSE11QuestionStepAnswer1 = ORKTextAnswerFormat(maximumLength: 30)
MMSE11QuestionStepAnswer1.multipleLines = false
let MMSE11QuestionStep1 = ORKQuestionStep(identifier: "11word1", title: MMSE11QuestionStepTitle1, question: "What was the first word?", answer: MMSE11QuestionStepAnswer1)
MMSE11QuestionStep1.isOptional = false
// Word 2
let MMSE11QuestionStepTitle2 = "Question 11"
let MMSE11QuestionStepAnswer2 = ORKTextAnswerFormat(maximumLength: 30)
MMSE11QuestionStepAnswer2.multipleLines = false
let MMSE11QuestionStep2 = ORKQuestionStep(identifier: "11word2", title: MMSE11QuestionStepTitle2, question: "What was the second word?", answer: MMSE11QuestionStepAnswer2)
MMSE11QuestionStep2.isOptional = false
// Word 3
let MMSE11QuestionStepTitle3 = "Question 11"
let MMSE11QuestionStepAnswer3 = ORKTextAnswerFormat(maximumLength: 30)
MMSE11QuestionStepAnswer3.multipleLines = false
let MMSE11QuestionStep3 = ORKQuestionStep(identifier: "11word3", title: MMSE11QuestionStepTitle3, question: "What was the third word?", answer: MMSE11QuestionStepAnswer3)
MMSE11QuestionStep3.isOptional = false
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Section 3
let sec3 = ORKInstructionStep(identifier: "Sec3")
sec3.title = "Concentration and Calculation"
sec3.detailText = "Without using a calculator, answer the following questions"
// Question 12
let subtract1 = ORKInstructionStep(identifier: "subtract1")
subtract1.title = "Question 12"
subtract1.detailText = "You have 100 pesos, and you will subtract 7 repeatedly"
// Subtraction 1
let MMSE12QuestionStepTitle1 = "Question 12"
let MMSE12QuestionStepAnswer1 = ORKTextAnswerFormat(maximumLength: 30)
MMSE12QuestionStepAnswer1.multipleLines = false
let MMSE12QuestionStep1 = ORKQuestionStep(identifier: "12subtract1", title: MMSE12QuestionStepTitle1, question: "100-7?", answer: MMSE12QuestionStepAnswer1)
MMSE12QuestionStep1.isOptional = false
// Subtraction 2
let MMSE12QuestionStepTitle2 = "Question 12"
let MMSE12QuestionStepAnswer2 = ORKTextAnswerFormat(maximumLength: 30)
MMSE12QuestionStepAnswer2.multipleLines = false
let MMSE12QuestionStep2 = ORKQuestionStep(identifier: "12subtract2", title: MMSE12QuestionStepTitle2, question: "Your previous result - 7?", answer: MMSE12QuestionStepAnswer2)
MMSE12QuestionStep2.isOptional = false
// Subtraction 3
let MMSE12QuestionStepTitle3 = "Question 12"
let MMSE12QuestionStepAnswer3 = ORKTextAnswerFormat(maximumLength: 30)
MMSE12QuestionStepAnswer3.multipleLines = false
let MMSE12QuestionStep3 = ORKQuestionStep(identifier: "12subtract3", title: MMSE12QuestionStepTitle3, question: "Your previous result - 7?", answer: MMSE12QuestionStepAnswer3)
MMSE12QuestionStep3.isOptional = false
// Subtraction 4
let MMSE12QuestionStepTitle4 = "Question 12"
let MMSE12QuestionStepAnswer4 = ORKTextAnswerFormat(maximumLength: 30)
MMSE12QuestionStepAnswer4.multipleLines = false
let MMSE12QuestionStep4 = ORKQuestionStep(identifier: "12subtract4", title: MMSE12QuestionStepTitle4, question: "Your previous result - 7?", answer: MMSE12QuestionStepAnswer4)
MMSE12QuestionStep4.isOptional = false
// Subtraction 5
let MMSE12QuestionStepTitle5 = "Question 12"
let MMSE12QuestionStepAnswer5 = ORKTextAnswerFormat(maximumLength: 30)
MMSE12QuestionStepAnswer5.multipleLines = false
let MMSE12QuestionStep5 = ORKQuestionStep(identifier: "12subtract5", title: MMSE12QuestionStepTitle5, question: "Your previous result - 7?", answer: MMSE12QuestionStepAnswer5)
MMSE12QuestionStep5.isOptional = false
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Section 4
let sec4 = ORKInstructionStep(identifier: "Sec4")
sec4.title = "Memory"
sec4.detailText = "Remember the 3 words we mentioned earlier, write them below"
// Question 13
// Word 1
let MMSE13QuestionStepTitle1 = "Question 13"
let MMSE13QuestionStepAnswer1 = ORKTextAnswerFormat(maximumLength: 30)
MMSE13QuestionStepAnswer1.multipleLines = false
let MMSE13QuestionStep1 = ORKQuestionStep(identifier: "13word1", title: MMSE13QuestionStepTitle1, question: "What was the first word?", answer: MMSE13QuestionStepAnswer1)
MMSE13QuestionStep1.isOptional = false
// Word 2
let MMSE13QuestionStepTitle2 = "Question 13"
let MMSE13QuestionStepAnswer2 = ORKTextAnswerFormat(maximumLength: 30)
MMSE13QuestionStepAnswer2.multipleLines = false
let MMSE13QuestionStep2 = ORKQuestionStep(identifier: "13word2", title: MMSE13QuestionStepTitle2, question: "What was the second word?", answer: MMSE13QuestionStepAnswer2)
MMSE13QuestionStep2.isOptional = false
// Word 3
let MMSE13QuestionStepTitle3 = "Question 13"
let MMSE13QuestionStepAnswer3 = ORKTextAnswerFormat(maximumLength: 30)
MMSE13QuestionStepAnswer3.multipleLines = false
let MMSE13QuestionStep3 = ORKQuestionStep(identifier: "13word3", title: MMSE13QuestionStepTitle3, question: "What was the third word?", answer: MMSE13QuestionStepAnswer3)
MMSE13QuestionStep3.isOptional = false
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Section 5
let sec5 = ORKInstructionStep(identifier: "Sec5")
sec5.title = "Language and Construction"
sec5.detailText = "Images will be shown, try to tell me what they are"
// Question 14
// Image 1
let MMSE14QuestionStepTitle1 = "Question 14"
// Text answer format
let MMSE14QuestionStepAnswer1 = ORKTextAnswerFormat(maximumLength: 30)
MMSE14QuestionStepAnswer1.multipleLines = false
// Create the question step with image for MMSE14
let MMSE14QuestionStep1 = ORKQuestionStep(
identifier: "14imageQuestion1",
title: MMSE14QuestionStepTitle1,
question: "What do you see in this image?",
answer: MMSE14QuestionStepAnswer1
)
MMSE14QuestionStep1.isOptional = false
// Add image to the step
MMSE14QuestionStep1.image = UIImage(named: "lapiz")
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Image 2
let MMSE14QuestionStepTitle2 = "Question 14"
// Text answer format
let MMSE14QuestionStepAnswer2 = ORKTextAnswerFormat(maximumLength: 30)
MMSE14QuestionStepAnswer2.multipleLines = false
// Create the question step with image for MMSE14
let MMSE14QuestionStep2 = ORKQuestionStep(
identifier: "14imageQuestion2",
title: MMSE14QuestionStepTitle2,
question: "What do you see in this image?",
answer: MMSE14QuestionStepAnswer2
)
MMSE14QuestionStep2.isOptional = false
// Add image to the step
MMSE14QuestionStep2.image = UIImage(named: "reloj")
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Question 15
let MMSE15QuestionStepTitle1 = "Question 15"
let MMSE15QuestionStepAnswer1 = ORKTextAnswerFormat(maximumLength: 30)
MMSE15QuestionStepAnswer1.multipleLines = false
let MMSE15QuestionStep1 = ORKQuestionStep(identifier: "15copy", title: MMSE15QuestionStepTitle1, question: "Repeat the phrase: No ifs, ands, or buts", answer: MMSE15QuestionStepAnswer1)
MMSE15QuestionStep1.isOptional = false
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Question 16
let ind16 = ORKInstructionStep(identifier: "ind16")
ind16.title = "Question 16"
ind16.detailText = "I will give you some instructions. Please follow them in the order I tell you: \n\n 1. Select the number 8 \n\n 2. Select all the words that start with P \n\n 3. Write the word 'hair'"
// Instruction 1
let MMSE16QuestionStepTitle1 = "Question 16"
let MMSE16QuestionStepAnswer1 = ORKScaleAnswerFormat(maximumValue: 12, minimumValue: 0, defaultValue: 4, step: 1)
let MMSE16QuestionStep1 = ORKQuestionStep(identifier: "16Instruction1", title: MMSE16QuestionStepTitle1, question: " ", answer: MMSE16QuestionStepAnswer1)
MMSE16QuestionStep1.isOptional = false
// Instruction 2
let MMSE16QuestionStepTitle2 = "Question 16"
let MMSE16QuestionChoices2 = [
ORKTextChoice(text: "Read", value: "Read" as NSString),
ORKTextChoice(text: "Dad", value: "Dad" as NSString),
ORKTextChoice(text: "Play", value: "Play" as NSString),
ORKTextChoice(text: "Bee", value: "Bee" as NSString),
ORKTextChoice(text: "Fight", value: "Fight" as NSString),
ORKTextChoice(text: "Drink", value: "Drink" as NSString),
ORKTextChoice(text: "Paper", value: "Paper" as NSString),
ORKTextChoice(text: "Popcorn", value: "Popcorn" as NSString),
ORKTextChoice(text: "Write", value: "Write" as NSString),
ORKTextChoice(text: "Dance", value: "Dance" as NSString),
ORKTextChoice(text: "Travel", value: "Travel" as NSString),
ORKTextChoice(text: "Comb", value: "Comb" as NSString)
]
let MMSE16QuestionStepAnswer2 = ORKTextChoiceAnswerFormat(style: .multipleChoice, textChoices: MMSE16QuestionChoices2)
MMSE13QuestionStepAnswer2.multipleLines = false
let MMSE16QuestionStep2 = ORKQuestionStep(identifier: "16Indicacion2", title: MMSE16QuestionStepTitle2, question: " ", answer: MMSE16QuestionStepAnswer2)
MMSE13QuestionStep2.isOptional = false
// Instruction 3
let MMSE16QuestionStepTitle3 = "Question 16"
let MMSE16QuestionStepAnswer3 = ORKTextAnswerFormat(maximumLength: 30)
MMSE16QuestionStepAnswer3.multipleLines = false
let MMSE16QuestionStep3 = ORKQuestionStep(identifier: "16Instruction3", title: MMSE16QuestionStepTitle3, question: " ", answer: MMSE16QuestionStepAnswer3)
MMSE16QuestionStep3.isOptional = false
// Question 17
let MMSE17QuestionStepTitle = "Question 17"
// Text answer format
let MMSE17QuestionStepAnswer = ORKTextAnswerFormat(maximumLength: 30)
MMSE17QuestionStepAnswer.multipleLines = false
// Create the image question step for MMSE17
let MMSE17QuestionStep = ORKQuestionStep(
identifier: "17ImageConstruction",
title: MMSE17QuestionStepTitle,
question: "Please do what the image says",
answer: MMSE17QuestionStepAnswer
)
MMSE17QuestionStep.isOptional = false
// Add the image to the step
MMSE17QuestionStep.image = UIImage(named: "name1")
// Question 18
let MMSE18QuestionStep = ORKQuestionStep(identifier: "18Sentence")
MMSE18QuestionStep.title = "Question 18"
MMSE18QuestionStep.question = "Write a sentence as if you were writing a letter."
MMSE18QuestionStep.answerFormat = ORKTextAnswerFormat(maximumLength: 200)
MMSE18QuestionStep.isOptional = false
// Question 19
let MMSE19QuestionStepTitle1 = "Question 19"
// Create the image-only question step
let MMSE19QuestionStep1 = ORKInstructionStep(identifier: "19Drawing1")
MMSE19QuestionStep1.title = MMSE19QuestionStepTitle1
MMSE19QuestionStep1.detailText = "Memorize the image below and click (Next)"
// Add the image to the step
MMSE19QuestionStep1.image = UIImage(named: "dibujo")
let MMSE19QuestionStep2 = ORKSignatureStep(identifier: "19Drawing")
MMSE19QuestionStep2.title = "Draw"
MMSE19QuestionStep2.text = "Draw the image above"
// END
let completionStep = ORKCompletionStep(identifier: "MMSECompletion")
completionStep.title = "Thank you!"
completionStep.iconImage = UIImage(systemName: "checkmark.seal")
completionStep.text = "You have completed the MMSE test. Thank you for your participation!"
// Retorna la tarea combinando los pasos
return ORKOrderedTask(identifier: "MMSESurveyTask", steps: [mmseInfo, sec1, MMSE1QuestionStep, MMSE2QuestionStep, MMSE3QuestionStep, MMSE4QuestionStep, MMSE5QuestionStep, MMSE6QuestionStep, MMSE7QuestionStep, MMSE8QuestionStep, MMSE9QuestionStep, MMSE10QuestionStep, sec2, words1, MMSE11QuestionStep1, MMSE11QuestionStep2, MMSE11QuestionStep3, sec3, subtract1, MMSE12QuestionStep1, MMSE12QuestionStep2, MMSE12QuestionStep3, MMSE12QuestionStep4, MMSE12QuestionStep5, sec4, MMSE13QuestionStep1, MMSE13QuestionStep2, MMSE13QuestionStep3, sec5, MMSE14QuestionStep1, MMSE14QuestionStep2, MMSE15QuestionStep1, ind16, MMSE16QuestionStep1, MMSE16QuestionStep2, MMSE16QuestionStep3, MMSE17QuestionStep, MMSE18QuestionStep,MMSE19QuestionStep1, MMSE19QuestionStep2, completionStep])
}
}
And the same form like consent, questionnaires needs to asign a button for trigger a window of formulaire. So the button need to drag to the ViewController, and put the next code:
IPAQ:
import UIKit
import ResearchKitUI
import ResearchKit
class IPAQViewController: UIViewController, ORKTaskViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func ipaqButton(_ sender: UIButton) {
let task = IPAQManager.shared.createIPAQ()
let taskViewController = ORKTaskViewController(task: task, taskRun: nil)
taskViewController.modalPresentationStyle = .fullScreen
taskViewController.delegate = self
present(taskViewController, animated: true, completion: nil)
}
func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskFinishReason, error: (any Error)?) {
taskViewController.dismiss(animated: true, completion: nil)
}
}
MMSE:
import UIKit
import ResearchKitUI
import ResearchKit
class MMSEViewController: UIViewController, ORKTaskViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func mmseButton(_ sender: UIButton) {
let task = MMSEManager.shared.createMMSE()
let taskViewController = ORKTaskViewController(task: task, taskRun: nil)
taskViewController.modalPresentationStyle = .fullScreen
taskViewController.delegate = self
present(taskViewController, animated: true, completion: nil)
}
func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskFinishReason, error: (any Error)?) {
taskViewController.dismiss(animated: true, completion: nil)
}
}
Now let's see how it show in the next GIF's