From 279edc53a5b9de0058469bdbac0a8f73bcdebc2f Mon Sep 17 00:00:00 2001 From: Umer Khan Date: Tue, 27 Sep 2016 13:37:04 -0700 Subject: [PATCH] convergence --- .gitmodules | 1 + CareKit.xcodeproj/project.pbxproj | 11 +- .../xcshareddata/xcschemes/CareKit.xcscheme | 2 +- CareKit/CareCard/OCKCareCardTableViewCell.m | 2 +- CareKit/CareCard/OCKCareCardViewController.m | 5 +- CareKit/CarePlan/OCKCarePlanStore.h | 5 + CareKit/CarePlan/OCKCarePlanStore.m | 6 + .../Connect/OCKConnectDetailViewController.m | 2 + CareKit/Insights/OCKGroupedBarChartView.m | 3 +- RELEASE-NOTES.md | 34 + Sample/OCKSample.xcodeproj/project.pbxproj | 354 ++++++++- Sample/OCKSample/Activity.swift | 14 +- Sample/OCKSample/AppDelegate.swift | 19 +- Sample/OCKSample/Assessment.swift | 8 +- .../AppIcon.appiconset/Contents.json | 136 +++- .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 1144 bytes .../Icon-App-20x20@2x-1.png | Bin 0 -> 1018 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1018 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1428 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 730 bytes .../Icon-App-29x29@2x-1.png | Bin 0 -> 1176 bytes .../Icon-App-29x29@2x-2.png | Bin 0 -> 1176 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 942 bytes .../Icon-App-40x40@2x-1.png | Bin 0 -> 1457 bytes .../Icon-App-40x40@2x-2.png | Bin 0 -> 1457 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2011 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2011 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 4352 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1387 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3680 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 4033 bytes .../Icon-Homescreen-24x24@2x.png | Bin 0 -> 947 bytes .../Icon-Homescreen-27.5x27.5@2x.png | Bin 0 -> 1036 bytes .../Icon-Homescreen-29x29@2x.png | Bin 0 -> 1058 bytes .../Icon-Homescreen-29x29@3x-1.png | Bin 0 -> 1423 bytes .../Icon-Homescreen-29x29@3x.png | Bin 0 -> 1423 bytes .../Icon-Homescreen-40x40@2x.png | Bin 0 -> 1393 bytes .../Icon-Homescreen-86x86@2x.png | Bin 0 -> 3836 bytes .../Icon-Homescreen-98x98@2x.png | Bin 0 -> 4305 bytes Sample/OCKSample/BackPain.swift | 14 +- Sample/OCKSample/BloodGlucose.swift | 20 +- Sample/OCKSample/BuildInsightsOperation.swift | 74 +- Sample/OCKSample/CarePlanStoreManager.swift | 22 +- Sample/OCKSample/Colors.swift | 16 +- Sample/OCKSample/HamstringStretch.swift | 12 +- Sample/OCKSample/HealthSampleBuilder.swift | 4 +- Sample/OCKSample/InsightsBuilder.swift | 32 +- Sample/OCKSample/Mood.swift | 14 +- Sample/OCKSample/NSCalendar+Dates.swift | 14 +- .../OCKInsightItem+EmptyMessage.swift | 2 +- Sample/OCKSample/OutdoorWalk.swift | 14 +- .../QueryActivityEventsOperation.swift | 46 +- Sample/OCKSample/RootViewController.swift | 68 +- Sample/OCKSample/SampleData.swift | 60 +- Sample/OCKSample/TakeMedication.swift | 12 +- .../OCKSample/WatchConnectivityManager.swift | 299 ++++++++ Sample/OCKSample/Weight.swift | 44 +- .../ActivityRow.swift | 49 ++ .../Circular.imageset/Contents.json | 27 + .../circular-stack-38mm@2x.png | Bin 0 -> 286 bytes .../circular-stack-42mm@2x.png | Bin 0 -> 314 bytes .../Contents.json | 26 + .../Modular.imageset/Contents.json | 27 + .../mod-small-stack-38mm@2x.png | Bin 0 -> 543 bytes .../mod-small-stack-42mm@2x.png | Bin 0 -> 587 bytes .../Utilitarian.imageset/Contents.json | 27 + .../utilitarian-38mm@2x.png | Bin 0 -> 366 bytes .../utilitarian-42mm@2x.png | Bin 0 -> 393 bytes .../X-Large.imageset/Contents.json | 23 + .../X-Large.imageset/xl-stack-38mm@2x.png | Bin 0 -> 1699 bytes .../X-Large.imageset/xl-stack-42mm@2x.png | Bin 0 -> 1868 bytes .../Assets.xcassets/Contents.json | 6 + .../ComplicationController.swift | 171 +++++ .../OCKSampleWatch Extension/EventRow.swift | 101 +++ .../ExtensionDelegate.swift | 47 ++ Sample/OCKSampleWatch Extension/Info.plist | 49 ++ .../InterfaceController.swift | 446 +++++++++++ .../WCKActivity.swift | 82 ++ .../OCKSampleWatch Extension/WCKEvent.swift | 63 ++ .../Base.lproj/Images.xcassets/Contents.json | 6 + .../bubble-empty.imageset/Contents.json | 27 + .../bubble-empty-42mm@2x.png | Bin 0 -> 2159 bytes .../bubble-empty.imageset/bubble-empty@2x.png | Bin 0 -> 1943 bytes .../bubble-fill.imageset/Contents.json | 27 + .../bubble-fill-38mm@2x.png | Bin 0 -> 1230 bytes .../bubble-fill-42mm@2x.png | Bin 0 -> 1365 bytes .../loader_sequence/Contents.json | 6 + .../loader0.imageset/Contents.json | 21 + .../loader0.imageset/loader_00000@2x.png | Bin 0 -> 1615 bytes .../loader1.imageset/Contents.json | 21 + .../loader1.imageset/loader_00001@2x.png | Bin 0 -> 1622 bytes .../loader10.imageset/Contents.json | 21 + .../loader10.imageset/loader_00010@2x.png | Bin 0 -> 2035 bytes .../loader11.imageset/Contents.json | 21 + .../loader11.imageset/loader_00011@2x.png | Bin 0 -> 2108 bytes .../loader12.imageset/Contents.json | 21 + .../loader12.imageset/loader_00012@2x.png | Bin 0 -> 2331 bytes .../loader13.imageset/Contents.json | 21 + .../loader13.imageset/loader_00013@2x.png | Bin 0 -> 2401 bytes .../loader14.imageset/Contents.json | 21 + .../loader14.imageset/loader_00014@2x.png | Bin 0 -> 2537 bytes .../loader15.imageset/Contents.json | 21 + .../loader15.imageset/loader_00015@2x.png | Bin 0 -> 2515 bytes .../loader16.imageset/Contents.json | 21 + .../loader16.imageset/loader_00016@2x.png | Bin 0 -> 2540 bytes .../loader17.imageset/Contents.json | 21 + .../loader17.imageset/loader_00017@2x.png | Bin 0 -> 2405 bytes .../loader18.imageset/Contents.json | 21 + .../loader18.imageset/loader_00018@2x.png | Bin 0 -> 2283 bytes .../loader19.imageset/Contents.json | 21 + .../loader19.imageset/loader_00019@2x.png | Bin 0 -> 2112 bytes .../loader2.imageset/Contents.json | 21 + .../loader2.imageset/loader_00002@2x.png | Bin 0 -> 1615 bytes .../loader20.imageset/Contents.json | 21 + .../loader20.imageset/loader_00020@2x.png | Bin 0 -> 2060 bytes .../loader21.imageset/Contents.json | 21 + .../loader21.imageset/loader_00021@2x.png | Bin 0 -> 1982 bytes .../loader22.imageset/Contents.json | 21 + .../loader22.imageset/loader_00022@2x.png | Bin 0 -> 1852 bytes .../loader23.imageset/Contents.json | 21 + .../loader23.imageset/loader_00023@2x.png | Bin 0 -> 1796 bytes .../loader24.imageset/Contents.json | 21 + .../loader24.imageset/loader_00024@2x.png | Bin 0 -> 1739 bytes .../loader25.imageset/Contents.json | 21 + .../loader25.imageset/loader_00025@2x.png | Bin 0 -> 1715 bytes .../loader26.imageset/Contents.json | 21 + .../loader26.imageset/loader_00026@2x.png | Bin 0 -> 1632 bytes .../loader27.imageset/Contents.json | 21 + .../loader27.imageset/loader_00027@2x.png | Bin 0 -> 1640 bytes .../loader28.imageset/Contents.json | 21 + .../loader28.imageset/loader_00028@2x.png | Bin 0 -> 1615 bytes .../loader3.imageset/Contents.json | 21 + .../loader3.imageset/loader_00003@2x.png | Bin 0 -> 1624 bytes .../loader4.imageset/Contents.json | 21 + .../loader4.imageset/loader_00004@2x.png | Bin 0 -> 1641 bytes .../loader5.imageset/Contents.json | 21 + .../loader5.imageset/loader_00005@2x.png | Bin 0 -> 1693 bytes .../loader6.imageset/Contents.json | 21 + .../loader6.imageset/loader_00006@2x.png | Bin 0 -> 1727 bytes .../loader7.imageset/Contents.json | 21 + .../loader7.imageset/loader_00007@2x.png | Bin 0 -> 1786 bytes .../loader8.imageset/Contents.json | 21 + .../loader8.imageset/loader_00008@2x.png | Bin 0 -> 1820 bytes .../loader9.imageset/Contents.json | 21 + .../loader9.imageset/loader_00009@2x.png | Bin 0 -> 1934 bytes .../Base.lproj/Interface.storyboard | 99 +++ Sample/OCKSampleWatch/Info.plist | 35 + dependency | 2 +- .../OCKTest/OCKTest.xcodeproj/project.pbxproj | 18 +- .../xcschemes/OCKTest-iPad.xcscheme | 2 +- .../xcshareddata/xcschemes/OCKTest.xcscheme | 22 +- testing/OCKTest/OCKTest/AppDelegate.h | 40 + testing/OCKTest/OCKTest/AppDelegate.m | 68 ++ testing/OCKTest/OCKTest/AppDelegate.swift | 22 +- .../AppIcon.appiconset/Contents.json | 20 + .../OCKTest/OCKTest/BarChartViewController.h | 37 + .../OCKTest/OCKTest/BarChartViewController.m | 182 +++++ .../OCKTest/BarChartViewController.swift | 46 +- .../OCKTest/CareCardTableViewController.swift | 271 +++---- .../OCKTest/ConnectTableViewController.swift | 98 +-- testing/OCKTest/OCKTest/CustomChart.swift | 34 +- .../OCKTest/OCKTest/DocumentViewController.h | 37 + .../OCKTest/OCKTest/DocumentViewController.m | 111 +++ .../DocumentsTableViewController.swift | 62 +- .../OCKTest/InsightsTableViewController.swift | 146 ++-- .../OCKTest/OCKTest/MainTableViewController.h | 37 + .../OCKTest/OCKTest/MainTableViewController.m | 706 ++++++++++++++++++ .../SymptomTrackerTableViewController.swift | 315 ++++---- .../OCKTest/ar.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/ar.lproj/Main.strings | 3 + .../OCKTest/ca.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/ca.lproj/Main.strings | 3 + .../OCKTest/cs.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/cs.lproj/Main.strings | 3 + .../OCKTest/da-DK.lproj/LaunchScreen.strings | 1 + .../OCKTest/OCKTest/da-DK.lproj/Main.strings | 3 + .../OCKTest/da.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/da.lproj/Main.strings | 3 + .../OCKTest/de.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/de.lproj/Main.strings | 3 + .../OCKTest/el.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/el.lproj/Main.strings | 3 + .../OCKTest/en-AU.lproj/LaunchScreen.strings | 1 + .../OCKTest/OCKTest/en-AU.lproj/Main.strings | 3 + .../OCKTest/en-GB.lproj/LaunchScreen.strings | 1 + .../OCKTest/OCKTest/en-GB.lproj/Main.strings | 3 + .../OCKTest/es-MX.lproj/LaunchScreen.strings | 1 + .../OCKTest/OCKTest/es-MX.lproj/Main.strings | 3 + .../OCKTest/es.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/es.lproj/Main.strings | 3 + .../OCKTest/fi-FI.lproj/LaunchScreen.strings | 1 + .../OCKTest/OCKTest/fi-FI.lproj/Main.strings | 3 + .../OCKTest/fi.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/fi.lproj/Main.strings | 3 + .../OCKTest/fr-CA.lproj/LaunchScreen.strings | 1 + .../OCKTest/OCKTest/fr-CA.lproj/Main.strings | 3 + .../OCKTest/fr.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/fr.lproj/Main.strings | 3 + .../OCKTest/he.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/he.lproj/Main.strings | 3 + .../OCKTest/hi.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/hi.lproj/Main.strings | 3 + .../OCKTest/hr.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/hr.lproj/Main.strings | 3 + .../OCKTest/hu-HU.lproj/LaunchScreen.strings | 1 + .../OCKTest/OCKTest/hu-HU.lproj/Main.strings | 3 + .../OCKTest/hu.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/hu.lproj/Main.strings | 3 + .../OCKTest/id.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/id.lproj/Main.strings | 3 + .../OCKTest/it.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/it.lproj/Main.strings | 3 + .../OCKTest/ja.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/ja.lproj/Main.strings | 3 + .../OCKTest/ko.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/ko.lproj/Main.strings | 3 + testing/OCKTest/OCKTest/main.m | 40 + .../OCKTest/ms.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/ms.lproj/Main.strings | 3 + .../OCKTest/nb.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/nb.lproj/Main.strings | 3 + .../OCKTest/nl.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/nl.lproj/Main.strings | 3 + .../OCKTest/pl.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/pl.lproj/Main.strings | 3 + .../OCKTest/pt-PT.lproj/LaunchScreen.strings | 1 + .../OCKTest/OCKTest/pt-PT.lproj/Main.strings | 3 + .../OCKTest/pt.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/pt.lproj/Main.strings | 3 + .../OCKTest/ro.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/ro.lproj/Main.strings | 3 + .../OCKTest/ru.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/ru.lproj/Main.strings | 3 + .../OCKTest/sk.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/sk.lproj/Main.strings | 3 + .../OCKTest/sv.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/sv.lproj/Main.strings | 3 + .../OCKTest/th.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/th.lproj/Main.strings | 3 + .../OCKTest/tr.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/tr.lproj/Main.strings | 3 + .../OCKTest/uk.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/uk.lproj/Main.strings | 3 + .../OCKTest/vi.lproj/LaunchScreen.strings | 1 + testing/OCKTest/OCKTest/vi.lproj/Main.strings | 3 + .../OCKTest/zh-HK.lproj/LaunchScreen.strings | 1 + .../OCKTest/OCKTest/zh-HK.lproj/Main.strings | 3 + .../zh-Hans.lproj/LaunchScreen.strings | 1 + .../OCKTest/zh-Hans.lproj/Main.strings | 3 + .../zh-Hant.lproj/LaunchScreen.strings | 1 + .../OCKTest/zh-Hant.lproj/Main.strings | 3 + testing/OCKTest/OCKTestTests/Info.plist | 24 + testing/OCKTest/OCKTestTests/OCKTestTests.m | 356 +++++++++ testing/OCKTest/OCKTestUITests/Info.plist | 24 + .../OCKTest/OCKTestUITests/OCKTestUITests.m | 64 ++ 255 files changed, 5498 insertions(+), 772 deletions(-) create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-2.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-2.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-24x24@2x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-27.5x27.5@2x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@2x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@3x-1.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@3x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-40x40@2x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-86x86@2x.png create mode 100644 Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-98x98@2x.png create mode 100644 Sample/OCKSample/WatchConnectivityManager.swift create mode 100644 Sample/OCKSampleWatch Extension/ActivityRow.swift create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/circular-stack-38mm@2x.png create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/circular-stack-42mm@2x.png create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Contents.json create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/mod-small-stack-38mm@2x.png create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/mod-small-stack-42mm@2x.png create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/utilitarian-38mm@2x.png create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/utilitarian-42mm@2x.png create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/X-Large.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/X-Large.imageset/xl-stack-38mm@2x.png create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/X-Large.imageset/xl-stack-42mm@2x.png create mode 100644 Sample/OCKSampleWatch Extension/Assets.xcassets/Contents.json create mode 100644 Sample/OCKSampleWatch Extension/ComplicationController.swift create mode 100644 Sample/OCKSampleWatch Extension/EventRow.swift create mode 100644 Sample/OCKSampleWatch Extension/ExtensionDelegate.swift create mode 100644 Sample/OCKSampleWatch Extension/Info.plist create mode 100644 Sample/OCKSampleWatch Extension/InterfaceController.swift create mode 100644 Sample/OCKSampleWatch Extension/WCKActivity.swift create mode 100644 Sample/OCKSampleWatch Extension/WCKEvent.swift create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-empty.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-empty.imageset/bubble-empty-42mm@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-empty.imageset/bubble-empty@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-fill.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-fill.imageset/bubble-fill-38mm@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-fill.imageset/bubble-fill-42mm@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader0.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader0.imageset/loader_00000@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader1.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader1.imageset/loader_00001@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader10.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader10.imageset/loader_00010@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader11.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader11.imageset/loader_00011@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader12.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader12.imageset/loader_00012@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader13.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader13.imageset/loader_00013@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader14.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader14.imageset/loader_00014@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader15.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader15.imageset/loader_00015@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader16.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader16.imageset/loader_00016@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader17.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader17.imageset/loader_00017@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader18.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader18.imageset/loader_00018@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader19.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader19.imageset/loader_00019@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader2.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader2.imageset/loader_00002@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader20.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader20.imageset/loader_00020@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader21.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader21.imageset/loader_00021@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader22.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader22.imageset/loader_00022@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader23.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader23.imageset/loader_00023@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader24.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader24.imageset/loader_00024@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader25.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader25.imageset/loader_00025@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader26.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader26.imageset/loader_00026@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader27.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader27.imageset/loader_00027@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader28.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader28.imageset/loader_00028@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader3.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader3.imageset/loader_00003@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader4.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader4.imageset/loader_00004@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader5.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader5.imageset/loader_00005@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader6.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader6.imageset/loader_00006@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader7.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader7.imageset/loader_00007@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader8.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader8.imageset/loader_00008@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader9.imageset/Contents.json create mode 100644 Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader9.imageset/loader_00009@2x.png create mode 100644 Sample/OCKSampleWatch/Base.lproj/Interface.storyboard create mode 100644 Sample/OCKSampleWatch/Info.plist create mode 100644 testing/OCKTest/OCKTest/AppDelegate.h create mode 100644 testing/OCKTest/OCKTest/AppDelegate.m create mode 100644 testing/OCKTest/OCKTest/BarChartViewController.h create mode 100644 testing/OCKTest/OCKTest/BarChartViewController.m create mode 100644 testing/OCKTest/OCKTest/DocumentViewController.h create mode 100644 testing/OCKTest/OCKTest/DocumentViewController.m create mode 100644 testing/OCKTest/OCKTest/MainTableViewController.h create mode 100644 testing/OCKTest/OCKTest/MainTableViewController.m create mode 100644 testing/OCKTest/OCKTest/ar.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/ar.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/ca.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/ca.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/cs.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/cs.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/da-DK.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/da-DK.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/da.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/da.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/de.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/de.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/el.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/el.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/en-AU.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/en-AU.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/en-GB.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/en-GB.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/es-MX.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/es-MX.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/es.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/es.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/fi-FI.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/fi-FI.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/fi.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/fi.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/fr-CA.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/fr-CA.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/fr.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/fr.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/he.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/he.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/hi.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/hi.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/hr.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/hr.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/hu-HU.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/hu-HU.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/hu.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/hu.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/id.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/id.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/it.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/it.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/ja.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/ja.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/ko.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/ko.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/main.m create mode 100644 testing/OCKTest/OCKTest/ms.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/ms.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/nb.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/nb.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/nl.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/nl.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/pl.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/pl.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/pt-PT.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/pt-PT.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/pt.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/pt.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/ro.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/ro.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/ru.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/ru.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/sk.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/sk.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/sv.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/sv.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/th.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/th.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/tr.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/tr.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/uk.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/uk.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/vi.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/vi.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/zh-HK.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/zh-HK.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/zh-Hans.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/zh-Hans.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTest/zh-Hant.lproj/LaunchScreen.strings create mode 100644 testing/OCKTest/OCKTest/zh-Hant.lproj/Main.strings create mode 100644 testing/OCKTest/OCKTestTests/Info.plist create mode 100644 testing/OCKTest/OCKTestTests/OCKTestTests.m create mode 100644 testing/OCKTest/OCKTestUITests/Info.plist create mode 100644 testing/OCKTest/OCKTestUITests/OCKTestUITests.m diff --git a/.gitmodules b/.gitmodules index 3496b0a31..4a19c025d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,4 @@ path = dependency url = https://github.com/ResearchKit/ResearchKit.git branch = stable + diff --git a/CareKit.xcodeproj/project.pbxproj b/CareKit.xcodeproj/project.pbxproj index 52661dc82..de3a455be 100644 --- a/CareKit.xcodeproj/project.pbxproj +++ b/CareKit.xcodeproj/project.pbxproj @@ -811,17 +811,20 @@ 8605A5B11C4F04EC00DD65FF /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = carekit.org; TargetAttributes = { 8605A5B91C4F04EC00DD65FF = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; 8605A5C31C4F04EC00DD65FF = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; 86189D081CC06A75006C74F0 = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0800; }; }; }; @@ -1051,6 +1054,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -1098,6 +1102,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -1150,6 +1155,7 @@ PRODUCT_BUNDLE_IDENTIFIER = org.carekit.CareKit; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -1168,6 +1174,7 @@ PRODUCT_BUNDLE_IDENTIFIER = org.carekit.CareKit; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -1181,6 +1188,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "CareKitTests/CareKitTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -1193,6 +1201,7 @@ PRODUCT_BUNDLE_IDENTIFIER = org.carekit.CareKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "CareKitTests/CareKitTests-Bridging-Header.h"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/CareKit.xcodeproj/xcshareddata/xcschemes/CareKit.xcscheme b/CareKit.xcodeproj/xcshareddata/xcschemes/CareKit.xcscheme index 1ddd4fb96..ff1374117 100644 --- a/CareKit.xcodeproj/xcshareddata/xcschemes/CareKit.xcscheme +++ b/CareKit.xcodeproj/xcshareddata/xcschemes/CareKit.xcscheme @@ -1,6 +1,6 @@ delegate; +/** +You can use the watch delegate to subscribe a watch app to notifications of changes to the store. + */ +@property (nonatomic, weak) id watchDelegate; + /** Add an activity to this store. diff --git a/CareKit/CarePlan/OCKCarePlanStore.m b/CareKit/CarePlan/OCKCarePlanStore.m index c052a1c7a..1aeb50b73 100644 --- a/CareKit/CarePlan/OCKCarePlanStore.m +++ b/CareKit/CarePlan/OCKCarePlanStore.m @@ -424,6 +424,9 @@ - (void)handleActivityListChange:(BOOL)result type:(OCKCarePlanActivityType)type if (_delegate && [_delegate respondsToSelector:@selector(carePlanStoreActivityListDidChange:)]) { [_delegate carePlanStoreActivityListDidChange:self]; } + if (_watchDelegate && [_watchDelegate respondsToSelector:@selector(carePlanStoreActivityListDidChange:)]) { + [_watchDelegate carePlanStoreActivityListDidChange:self]; + } }); } } @@ -757,6 +760,9 @@ - (void)updateEvent:(OCKCarePlanEvent *)event if(_delegate && [_delegate respondsToSelector:@selector(carePlanStore:didReceiveUpdateOfEvent:)]) { [_delegate carePlanStore:self didReceiveUpdateOfEvent:copiedEvent]; } + if(_watchDelegate && [_watchDelegate respondsToSelector:@selector(carePlanStore:didReceiveUpdateOfEvent:)]) { + [_watchDelegate carePlanStore:self didReceiveUpdateOfEvent:copiedEvent]; + } }); } }); diff --git a/CareKit/Connect/OCKConnectDetailViewController.m b/CareKit/Connect/OCKConnectDetailViewController.m index f35ca2fff..c014ba4c8 100644 --- a/CareKit/Connect/OCKConnectDetailViewController.m +++ b/CareKit/Connect/OCKConnectDetailViewController.m @@ -297,6 +297,7 @@ - (void)messageComposeViewController:(MFMessageComposeViewController *)controlle } } + #pragma mark - MFMailComposeViewControllerDelegate - (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error { @@ -309,6 +310,7 @@ - (void)mailComposeController:(MFMailComposeViewController *)controller didFinis } } + #pragma mark - Preview Action Items - (NSArray> *)previewActionItems { diff --git a/CareKit/Insights/OCKGroupedBarChartView.m b/CareKit/Insights/OCKGroupedBarChartView.m index 7523f4ed3..ed2d64047 100644 --- a/CareKit/Insights/OCKGroupedBarChartView.m +++ b/CareKit/Insights/OCKGroupedBarChartView.m @@ -157,6 +157,7 @@ - (void)layoutSubviews { } - (void)prepareView { + self.backgroundColor = [UIColor whiteColor]; _barView = [UIView new]; @@ -182,7 +183,7 @@ - (void)prepareView { NSMutableArray *constraints = [NSMutableArray new]; NSString *visualFormat = [NSString stringWithFormat:@"H:|[barView]-%f-[valueLabel]", MarginBetweenBarAndLabel]; - [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:visualFormat + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:visualFormat options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:views]]; diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 9fa27199d..2a0254438 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,5 +1,39 @@ # CareKit Release Notes +## CareKit 1.1 Release Notes + +*CareKit 1.1* supports *iOS* and requires *Xcode 8.0* or later. The minimum supported *Base SDK* is *9.0*. + +*CareKit 1.1* includes the following new features and enhancements. + +- **Care Card on Apple Watch** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + The *Sample App* (OCKSample project in CareKit's workspace) now includes a watch app. The app works out of the box. Included in the Watch group is the *Watch Connectivity Manager* which abstracts the logic of communicating the *Care Card* data between the phone and the watch. + + The *Care Plan Store* has also been updated to support Apple Watch. + +- **New Test App** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + The *New Test App* is written entirely in Swift and provides extensive coverage for all CareKit Modules. + +- **Other Improvements** + + - **3D Touch Support** + + *Contributed by [Troy Tsubota](https://github.com/tktsubota).* + + The *Care Card* and *Connect* view controllers have been updated to support 3D Touch. In the *Care Card* view controller, a user can 3D Touch on an activity to peek and pop. In the *Connect* view controller, a user can peek, pop, and use perform actions right from the master screen. + + - **FaceTime in Connect** + + *Contributed by [Micah Hainline](https://github.com/micahhainline).* + + *FaceTime* calls can now be made from within the Connect module. Apart from *FaceTime* support, *Connect* now has the ability to create any custom method of communication (such as fax). + ## CareKit 1.0 Release Notes diff --git a/Sample/OCKSample.xcodeproj/project.pbxproj b/Sample/OCKSample.xcodeproj/project.pbxproj index 7a6353dbd..394f0a5a8 100644 --- a/Sample/OCKSample.xcodeproj/project.pbxproj +++ b/Sample/OCKSample.xcodeproj/project.pbxproj @@ -7,8 +7,23 @@ objects = { /* Begin PBXBuildFile section */ + 1801613F1D4E778F0036E247 /* WatchConnectivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1801613E1D4E778F0036E247 /* WatchConnectivityManager.swift */; }; + 18214FC81D3D9C8000AE765B /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 18214FC61D3D9C8000AE765B /* Interface.storyboard */; }; + 18214FD11D3D9C8000AE765B /* OCKSampleWatch Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 18214FD01D3D9C8000AE765B /* OCKSampleWatch Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 18214FD61D3D9C8000AE765B /* InterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18214FD51D3D9C8000AE765B /* InterfaceController.swift */; }; + 18214FD81D3D9C8000AE765B /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18214FD71D3D9C8000AE765B /* ExtensionDelegate.swift */; }; + 18214FDA1D3D9C8000AE765B /* ComplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18214FD91D3D9C8000AE765B /* ComplicationController.swift */; }; + 18214FE01D3D9C8000AE765B /* OCKSampleWatch.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 18214FC41D3D9C8000AE765B /* OCKSampleWatch.app */; }; + 18A9BB0C1D6B73A200E165E1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 18A9BB0B1D6B73A200E165E1 /* Assets.xcassets */; }; + 18B2F9021D4973B7005FFBC6 /* EventRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B2F9011D4973B7005FFBC6 /* EventRow.swift */; }; + 18F996761D4D6B7500A47E83 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 18F996741D4D6B7500A47E83 /* Images.xcassets */; }; + 18FB87471D3ED97200D2A06D /* WCKActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18FB87461D3ED97200D2A06D /* WCKActivity.swift */; }; + 18FB87491D3ED97A00D2A06D /* WCKEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18FB87481D3ED97A00D2A06D /* WCKEvent.swift */; }; + 18FB874F1D3F106200D2A06D /* ActivityRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18FB874E1D3F106200D2A06D /* ActivityRow.swift */; }; + 24026C671D6D244A007582F3 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24026C661D6D244A007582F3 /* HealthKit.framework */; }; 2436E4341CD18BFD00ABE381 /* ResearchKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2436E4311CD18BED00ABE381 /* ResearchKit.framework */; }; 2436E4351CD18BFD00ABE381 /* ResearchKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2436E4311CD18BED00ABE381 /* ResearchKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 24A69BBC1D779DE600BEAD84 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B5C100991CB12E0C00FAD7E8 /* Assets.xcassets */; }; B55565771CC82FCA00513644 /* CareKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B55565711CC82F8D00513644 /* CareKit.framework */; }; B55565781CC82FCA00513644 /* CareKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B55565711CC82F8D00513644 /* CareKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B555759C1CB3DB8C0028DC37 /* NSCalendar+Dates.swift in Sources */ = {isa = PBXBuildFile; fileRef = B555759B1CB3DB8C0028DC37 /* NSCalendar+Dates.swift */; }; @@ -37,6 +52,20 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 18214FD21D3D9C8000AE765B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B5C100851CB12E0C00FAD7E8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 18214FCF1D3D9C8000AE765B; + remoteInfo = "OCKSampleWatch Extension"; + }; + 18214FDE1D3D9C8000AE765B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B5C100851CB12E0C00FAD7E8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 18214FC31D3D9C8000AE765B; + remoteInfo = OCKSampleWatch; + }; 2436E4301CD18BED00ABE381 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 2436E42A1CD18BEC00ABE381 /* ResearchKit.xcodeproj */; @@ -82,6 +111,28 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 18214FE41D3D9C8000AE765B /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 18214FD11D3D9C8000AE765B /* OCKSampleWatch Extension.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + 18214FE81D3D9C8000AE765B /* Embed Watch Content */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(CONTENTS_FOLDER_PATH)/Watch"; + dstSubfolderSpec = 16; + files = ( + 18214FE01D3D9C8000AE765B /* OCKSampleWatch.app in Embed Watch Content */, + ); + name = "Embed Watch Content"; + runOnlyForDeploymentPostprocessing = 0; + }; B58E92701CB6C1E100E4CD4A /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -97,6 +148,22 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1801613E1D4E778F0036E247 /* WatchConnectivityManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WatchConnectivityManager.swift; path = OCKSample/WatchConnectivityManager.swift; sourceTree = ""; }; + 18214FC41D3D9C8000AE765B /* OCKSampleWatch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OCKSampleWatch.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 18214FC71D3D9C8000AE765B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = ""; }; + 18214FCB1D3D9C8000AE765B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 18214FD01D3D9C8000AE765B /* OCKSampleWatch Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "OCKSampleWatch Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + 18214FD51D3D9C8000AE765B /* InterfaceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterfaceController.swift; sourceTree = ""; }; + 18214FD71D3D9C8000AE765B /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = ""; }; + 18214FD91D3D9C8000AE765B /* ComplicationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComplicationController.swift; sourceTree = ""; }; + 18214FDD1D3D9C8000AE765B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 18A9BB0B1D6B73A200E165E1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 18B2F9011D4973B7005FFBC6 /* EventRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventRow.swift; sourceTree = ""; }; + 18F996751D4D6B7500A47E83 /* Base */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Base; path = Base.lproj/Images.xcassets; sourceTree = ""; }; + 18FB87461D3ED97200D2A06D /* WCKActivity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WCKActivity.swift; sourceTree = ""; }; + 18FB87481D3ED97A00D2A06D /* WCKEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WCKEvent.swift; sourceTree = ""; }; + 18FB874E1D3F106200D2A06D /* ActivityRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityRow.swift; sourceTree = ""; }; + 24026C661D6D244A007582F3 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; }; 2436E42A1CD18BEC00ABE381 /* ResearchKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ResearchKit.xcodeproj; path = ../dependency/ResearchKit.xcodeproj; sourceTree = ""; }; B555759B1CB3DB8C0028DC37 /* NSCalendar+Dates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSCalendar+Dates.swift"; sourceTree = ""; }; B555759D1CB3DBBE0028DC37 /* OCKInsightItem+EmptyMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OCKInsightItem+EmptyMessage.swift"; sourceTree = ""; }; @@ -128,10 +195,18 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 18214FCD1D3D9C8000AE765B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; B5C1008A1CB12E0C00FAD7E8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 24026C671D6D244A007582F3 /* HealthKit.framework in Frameworks */, 2436E4341CD18BFD00ABE381 /* ResearchKit.framework in Frameworks */, B55565771CC82FCA00513644 /* CareKit.framework in Frameworks */, ); @@ -140,6 +215,48 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 18214FC51D3D9C8000AE765B /* OCKSampleWatch */ = { + isa = PBXGroup; + children = ( + 18214FC61D3D9C8000AE765B /* Interface.storyboard */, + 18214FCB1D3D9C8000AE765B /* Info.plist */, + 18F996741D4D6B7500A47E83 /* Images.xcassets */, + ); + path = OCKSampleWatch; + sourceTree = ""; + }; + 18214FD41D3D9C8000AE765B /* OCKSampleWatch Extension */ = { + isa = PBXGroup; + children = ( + 18214FD51D3D9C8000AE765B /* InterfaceController.swift */, + 18214FD71D3D9C8000AE765B /* ExtensionDelegate.swift */, + 18214FD91D3D9C8000AE765B /* ComplicationController.swift */, + 18FB874E1D3F106200D2A06D /* ActivityRow.swift */, + 18B2F9011D4973B7005FFBC6 /* EventRow.swift */, + 1855F0F61D3DFCDA00D9E994 /* WCK Data Models */, + 18214FDD1D3D9C8000AE765B /* Info.plist */, + 18A9BB0B1D6B73A200E165E1 /* Assets.xcassets */, + ); + path = "OCKSampleWatch Extension"; + sourceTree = ""; + }; + 1855F0F61D3DFCDA00D9E994 /* WCK Data Models */ = { + isa = PBXGroup; + children = ( + 18FB87461D3ED97200D2A06D /* WCKActivity.swift */, + 18FB87481D3ED97A00D2A06D /* WCKEvent.swift */, + ); + name = "WCK Data Models"; + sourceTree = ""; + }; + 24026C651D6D244A007582F3 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 24026C661D6D244A007582F3 /* HealthKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 2436E42B1CD18BEC00ABE381 /* Products */ = { isa = PBXGroup; children = ( @@ -149,6 +266,16 @@ name = Products; sourceTree = ""; }; + 24E285101D74AE0A00F840E1 /* Watch */ = { + isa = PBXGroup; + children = ( + 1801613E1D4E778F0036E247 /* WatchConnectivityManager.swift */, + 18214FC51D3D9C8000AE765B /* OCKSampleWatch */, + 18214FD41D3D9C8000AE765B /* OCKSampleWatch Extension */, + ); + name = Watch; + sourceTree = ""; + }; B555656C1CC82F8D00513644 /* Products */ = { isa = PBXGroup; children = ( @@ -204,17 +331,19 @@ isa = PBXGroup; children = ( B5C1008F1CB12E0C00FAD7E8 /* OCKSample */, + 24E285101D74AE0A00F840E1 /* Watch */, B555657F1CC82FEF00513644 /* Linked frameworks */, B5C1008E1CB12E0C00FAD7E8 /* Products */, + 24026C651D6D244A007582F3 /* Frameworks */, ); - indentWidth = 4; sourceTree = ""; - tabWidth = 4; }; B5C1008E1CB12E0C00FAD7E8 /* Products */ = { isa = PBXGroup; children = ( B5C1008D1CB12E0C00FAD7E8 /* OCKSample.app */, + 18214FC41D3D9C8000AE765B /* OCKSampleWatch.app */, + 18214FD01D3D9C8000AE765B /* OCKSampleWatch Extension.appex */, ); name = Products; sourceTree = ""; @@ -253,6 +382,40 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 18214FC31D3D9C8000AE765B /* OCKSampleWatch */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18214FE51D3D9C8000AE765B /* Build configuration list for PBXNativeTarget "OCKSampleWatch" */; + buildPhases = ( + 18214FC21D3D9C8000AE765B /* Resources */, + 18214FE41D3D9C8000AE765B /* Embed App Extensions */, + ); + buildRules = ( + ); + dependencies = ( + 18214FD31D3D9C8000AE765B /* PBXTargetDependency */, + ); + name = OCKSampleWatch; + productName = OCKSampleWatch; + productReference = 18214FC41D3D9C8000AE765B /* OCKSampleWatch.app */; + productType = "com.apple.product-type.application.watchapp2"; + }; + 18214FCF1D3D9C8000AE765B /* OCKSampleWatch Extension */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18214FE11D3D9C8000AE765B /* Build configuration list for PBXNativeTarget "OCKSampleWatch Extension" */; + buildPhases = ( + 18214FCC1D3D9C8000AE765B /* Sources */, + 18214FCD1D3D9C8000AE765B /* Frameworks */, + 18214FCE1D3D9C8000AE765B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "OCKSampleWatch Extension"; + productName = "OCKSampleWatch Extension"; + productReference = 18214FD01D3D9C8000AE765B /* OCKSampleWatch Extension.appex */; + productType = "com.apple.product-type.watchkit2-extension"; + }; B5C1008C1CB12E0C00FAD7E8 /* OCKSample */ = { isa = PBXNativeTarget; buildConfigurationList = B5C100A11CB12E0C00FAD7E8 /* Build configuration list for PBXNativeTarget "OCKSample" */; @@ -261,12 +424,14 @@ B5C1008A1CB12E0C00FAD7E8 /* Frameworks */, B5C1008B1CB12E0C00FAD7E8 /* Resources */, B58E92701CB6C1E100E4CD4A /* Embed Frameworks */, + 18214FE81D3D9C8000AE765B /* Embed Watch Content */, ); buildRules = ( ); dependencies = ( B555657A1CC82FCA00513644 /* PBXTargetDependency */, 2436E4371CD18BFD00ABE381 /* PBXTargetDependency */, + 18214FDF1D3D9C8000AE765B /* PBXTargetDependency */, ); name = OCKSample; productName = OCKSample; @@ -280,11 +445,20 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0730; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = Apple; TargetAttributes = { + 18214FC31D3D9C8000AE765B = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0800; + }; + 18214FCF1D3D9C8000AE765B = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0800; + }; B5C1008C1CB12E0C00FAD7E8 = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0800; SystemCapabilities = { com.apple.HealthKit = { enabled = 1; @@ -317,6 +491,8 @@ projectRoot = ""; targets = ( B5C1008C1CB12E0C00FAD7E8 /* OCKSample */, + 18214FC31D3D9C8000AE765B /* OCKSampleWatch */, + 18214FCF1D3D9C8000AE765B /* OCKSampleWatch Extension */, ); }; /* End PBXProject section */ @@ -353,6 +529,24 @@ /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ + 18214FC21D3D9C8000AE765B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18F996761D4D6B7500A47E83 /* Images.xcassets in Resources */, + 24A69BBC1D779DE600BEAD84 /* Assets.xcassets in Resources */, + 18214FC81D3D9C8000AE765B /* Interface.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18214FCE1D3D9C8000AE765B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18A9BB0C1D6B73A200E165E1 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; B5C1008B1CB12E0C00FAD7E8 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -366,6 +560,20 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 18214FCC1D3D9C8000AE765B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18214FD81D3D9C8000AE765B /* ExtensionDelegate.swift in Sources */, + 18FB874F1D3F106200D2A06D /* ActivityRow.swift in Sources */, + 18214FD61D3D9C8000AE765B /* InterfaceController.swift in Sources */, + 18FB87471D3ED97200D2A06D /* WCKActivity.swift in Sources */, + 18214FDA1D3D9C8000AE765B /* ComplicationController.swift in Sources */, + 18B2F9021D4973B7005FFBC6 /* EventRow.swift in Sources */, + 18FB87491D3ED97A00D2A06D /* WCKEvent.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; B5C100891CB12E0C00FAD7E8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -389,6 +597,7 @@ B5C100DC1CB1547600FAD7E8 /* SampleData.swift in Sources */, B58A3FBD1CC81FF9009CF1B9 /* Mood.swift in Sources */, B5C100D51CB1475900FAD7E8 /* RootViewController.swift in Sources */, + 1801613F1D4E778F0036E247 /* WatchConnectivityManager.swift in Sources */, B5C01D521CB3BC2D000728D9 /* BuildInsightsOperation.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -396,6 +605,16 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 18214FD31D3D9C8000AE765B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 18214FCF1D3D9C8000AE765B /* OCKSampleWatch Extension */; + targetProxy = 18214FD21D3D9C8000AE765B /* PBXContainerItemProxy */; + }; + 18214FDF1D3D9C8000AE765B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 18214FC31D3D9C8000AE765B /* OCKSampleWatch */; + targetProxy = 18214FDE1D3D9C8000AE765B /* PBXContainerItemProxy */; + }; 2436E4371CD18BFD00ABE381 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = ResearchKit; @@ -409,6 +628,22 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ + 18214FC61D3D9C8000AE765B /* Interface.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 18214FC71D3D9C8000AE765B /* Base */, + ); + name = Interface.storyboard; + sourceTree = ""; + }; + 18F996741D4D6B7500A47E83 /* Images.xcassets */ = { + isa = PBXVariantGroup; + children = ( + 18F996751D4D6B7500A47E83 /* Base */, + ); + name = Images.xcassets; + sourceTree = ""; + }; B5C100961CB12E0C00FAD7E8 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( @@ -428,6 +663,85 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 18214FE21D3D9C8000AE765B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + ASSETCATALOG_NOTICES = NO; + ASSETCATALOG_WARNINGS = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = "OCKSampleWatch Extension/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.CareKit.watchkitapp.watchkitextension"; + PRODUCT_NAME = "${TARGET_NAME}"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 2.2; + }; + name = Debug; + }; + 18214FE31D3D9C8000AE765B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + ASSETCATALOG_NOTICES = NO; + ASSETCATALOG_WARNINGS = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = "OCKSampleWatch Extension/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.CareKit.watchkitapp.watchkitextension"; + PRODUCT_NAME = "${TARGET_NAME}"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 2.2; + }; + name = Release; + }; + 18214FE61D3D9C8000AE765B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; + IBSC_MODULE = OCKSampleWatch_Extension; + INFOPLIST_FILE = OCKSampleWatch/Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.CareKit.watchkitapp"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 2.2; + }; + name = Debug; + }; + 18214FE71D3D9C8000AE765B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; + IBSC_MODULE = OCKSampleWatch_Extension; + INFOPLIST_FILE = OCKSampleWatch/Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.CareKit.watchkitapp"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 2.2; + }; + name = Release; + }; B5C1009F1CB12E0C00FAD7E8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -442,8 +756,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -465,7 +781,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -487,8 +803,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -504,9 +822,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VALIDATE_PRODUCT = YES; }; name = Release; @@ -514,14 +833,15 @@ B5C100A21CB12E0C00FAD7E8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = OCKSample/OCKSample.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; INFOPLIST_FILE = OCKSample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.CareKit"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -529,14 +849,16 @@ B5C100A31CB12E0C00FAD7E8 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = OCKSample/OCKSample.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; INFOPLIST_FILE = OCKSample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.CareKit"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; @@ -544,6 +866,24 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 18214FE11D3D9C8000AE765B /* Build configuration list for PBXNativeTarget "OCKSampleWatch Extension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18214FE21D3D9C8000AE765B /* Debug */, + 18214FE31D3D9C8000AE765B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18214FE51D3D9C8000AE765B /* Build configuration list for PBXNativeTarget "OCKSampleWatch" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18214FE61D3D9C8000AE765B /* Debug */, + 18214FE71D3D9C8000AE765B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; B5C100881CB12E0C00FAD7E8 /* Build configuration list for PBXProject "OCKSample" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Sample/OCKSample/Activity.swift b/Sample/OCKSample/Activity.swift index 7a34e1f9f..4032fa7f3 100644 --- a/Sample/OCKSample/Activity.swift +++ b/Sample/OCKSample/Activity.swift @@ -45,12 +45,12 @@ protocol Activity { the app. */ enum ActivityType: String { - case OutdoorWalk - case HamstringStretch - case TakeMedication + case outdoorWalk + case hamstringStretch + case takeMedication - case BackPain - case Mood - case BloodGlucose - case Weight + case backPain + case mood + case bloodGlucose + case weight } diff --git a/Sample/OCKSample/AppDelegate.swift b/Sample/OCKSample/AppDelegate.swift index b088ddfdd..b48c8fad2 100644 --- a/Sample/OCKSample/AppDelegate.swift +++ b/Sample/OCKSample/AppDelegate.swift @@ -34,11 +34,20 @@ import UIKit class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - - - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { - window?.tintColor = Colors.Red.color + + #if swift(>=3.0) + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { + window?.tintColor = Colors.red.color + return true + } + + #else + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: Any]?) -> Bool { + window?.tintColor = Colors.red.color return true } -} \ No newline at end of file + + #endif +} diff --git a/Sample/OCKSample/Assessment.swift b/Sample/OCKSample/Assessment.swift index cbc8849c9..ab8a1b29a 100644 --- a/Sample/OCKSample/Assessment.swift +++ b/Sample/OCKSample/Assessment.swift @@ -46,15 +46,15 @@ protocol Assessment: Activity { `OCKCarePlanEventResult` can then be written to a `OCKCarePlanStore`. */ extension Assessment { - func buildResultForCarePlanEvent(event: OCKCarePlanEvent, taskResult: ORKTaskResult) -> OCKCarePlanEventResult { + func buildResultForCarePlanEvent(_ event: OCKCarePlanEvent, taskResult: ORKTaskResult) -> OCKCarePlanEventResult { // Get the first result for the first step of the task result. - guard let firstResult = taskResult.firstResult as? ORKStepResult, stepResult = firstResult.results?.first else { fatalError("Unexepected task results") } + guard let firstResult = taskResult.firstResult as? ORKStepResult, let stepResult = firstResult.results?.first else { fatalError("Unexepected task results") } // Determine what type of result should be saved. - if let scaleResult = stepResult as? ORKScaleQuestionResult, answer = scaleResult.scaleAnswer { + if let scaleResult = stepResult as? ORKScaleQuestionResult, let answer = scaleResult.scaleAnswer { return OCKCarePlanEventResult(valueString: answer.stringValue, unitString: "out of 10", userInfo: nil) } - else if let numericResult = stepResult as? ORKNumericQuestionResult, answer = numericResult.numericAnswer { + else if let numericResult = stepResult as? ORKNumericQuestionResult, let answer = numericResult.numericAnswer { return OCKCarePlanEventResult(valueString: answer.stringValue, unitString: numericResult.unit, userInfo: nil) } diff --git a/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Contents.json b/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Contents.json index 118c98f74..ce9cc0668 100644 --- a/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,34 +1,160 @@ { "images" : [ { + "size" : "20x20", "idiom" : "iphone", - "size" : "29x29", + "filename" : "Icon-App-20x20@2x-1.png", "scale" : "2x" }, { + "size" : "20x20", "idiom" : "iphone", - "size" : "29x29", + "filename" : "Icon-App-20x20@3x.png", "scale" : "3x" }, { + "size" : "29x29", "idiom" : "iphone", - "size" : "40x40", + "filename" : "Icon-App-29x29@2x-2.png", "scale" : "2x" }, { + "size" : "29x29", "idiom" : "iphone", - "size" : "40x40", + "filename" : "Icon-Homescreen-29x29@3x.png", "scale" : "3x" }, { + "size" : "40x40", "idiom" : "iphone", - "size" : "60x60", + "filename" : "Icon-App-40x40@2x-2.png", "scale" : "2x" }, { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x-1.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x-1.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "24x24", + "idiom" : "watch", + "filename" : "Icon-Homescreen-24x24@2x.png", + "scale" : "2x", + "role" : "notificationCenter", + "subtype" : "38mm" + }, + { + "size" : "27.5x27.5", + "idiom" : "watch", + "filename" : "Icon-Homescreen-27.5x27.5@2x.png", + "scale" : "2x", + "role" : "notificationCenter", + "subtype" : "42mm" + }, + { + "size" : "29x29", + "idiom" : "watch", + "filename" : "Icon-Homescreen-29x29@2x.png", + "role" : "companionSettings", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "watch", + "filename" : "Icon-Homescreen-29x29@3x-1.png", + "role" : "companionSettings", "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "watch", + "filename" : "Icon-Homescreen-40x40@2x.png", + "scale" : "2x", + "role" : "appLauncher", + "subtype" : "38mm" + }, + { + "size" : "86x86", + "idiom" : "watch", + "filename" : "Icon-Homescreen-86x86@2x.png", + "scale" : "2x", + "role" : "quickLook", + "subtype" : "38mm" + }, + { + "size" : "98x98", + "idiom" : "watch", + "filename" : "Icon-Homescreen-98x98@2x.png", + "scale" : "2x", + "role" : "quickLook", + "subtype" : "42mm" } ], "info" : { diff --git a/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..daa9bbff64797a61325dc87282d8bb7649721827 GIT binary patch literal 1144 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 QW&i*H07*qoM6N<$f>;2wcK`qY literal 0 HcmV?d00001 diff --git a/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png b/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..2c7e444383ceca012839f1808cee57bb056829a6 GIT binary patch literal 1457 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 LNkvXXu0mjfr@h3{quXhp3n1sKA-BR9 z?H;@%0Bqs;c?Wu+Si=9tB^b32fK3iVdd`rJJ+#Xf+GPW2*}{9V2<8at7>GIrAr{`S zfh(lz0BPAl+IG+$N7&c{vBjgVA*gc@y#FAiX+!ag-AKt}7FV-wHL`0Tv2NaD6jp8| zoTqr6f(_juO>5Z59r@W4(s!msWil?7u`23Wcbb@Gcj#GHse~lN(g)IWLJx+ZuEDTA zmKu`8s=Uj8Hz(rrH#av$3?^@El37|q4N8ReI5G0dxi5x=Fe+GDW#4V3#bu*T$56N9 zh=mWRX-y3{&FSo?hMt9g@&GlgDY$TUU5kjp;*GyY-9jnuq0Gv=oYpSH4$mzAb5kJT zbo9aI-n>`ugb0-uodv3yp$-Ay4ok}6ll6us94UZvhd(P7ryn$Ejx@O+sIIH>rw{L{g{(_!f z$gXdJjoqn)GmQLl#M)0l{*GArqAmpH_1m15=a7aC$iIQu`cb?hg)jwF!JrO-{P*)h3XOU! z0o-oEY3}4rOd}3~jDj1`J}jhxh{bjKT3HXF*LHdRig#_gYxbiQ7HE zpIM}5UKK(J^S4@dV>@?n96oS}8j{R=GbQ-+b>o*jNXKDQBoZvIF-xi`_&91{0%CGl z+>0#F$K7IVN%Qv&Aa6(;h17|iM5NbYccGVD`FF9ABYK9U0)V{Azmk|*CJDr$Od8I| zLuOT0TggUGdCEpY+(B)eyKCU-kH}IYF~CC&SWSEGQ$90g;A$;b8Kil{W4J7rVXP-B zr&wIN`<`KgM7-I_naBaX1i!`?2NaV`oc#i4)IF4?B;D&8$3pSvu*zy4c-l5zp79$@ z!IzKAsrKa>ag!?+b}Rq%<-}!9`YIGQOv>W&bj1{_q&Z{JF0OMjJ##FzE!G%0 zJrNg|Ztu`bw+owK-s~~R36*5MPo6{9nTCGXN4Pr}FW!BCBz>xuDsu1?=aLPW4b>wbTP!TDM#tBNK*x^qdC&2vKPs3rwI%%6NSjNJ-(kS#vht>j4@Vv6}~!L z-dAl{}?3zBikmFOieM5ZgM=G^^}yy>{Y3;b@rd{+yv} zWLMiaqw6aT!`GUNisWeRs%O#rmm)5Zi5~g}%k>r7OS5hl+raAPV$eOfLRaa! zZ@1gPaHE5fZ0y=YLqb)MRNnM7Iyf*g{W5QLO2d|bkDaJj%9=ZK;N0_BiQGr)Z$<{` zjWR&a*Ok12ikw8Ctydi}W>*2kiqu#%+R@`~7no(kJDuLg$t);S{)sn$9q!*)%; zba+V7E&R29RuDMNRlKc3nYd6p)cyKSX|Gn|;LI~EnSQF?4+DFvpKg(Q zd_rLu#U7xqg|o6nyFQ`!)AXNm4|=}aS+ifE zKcw~ZhUJ3wt%4oJCZUTej@~m(xX9$mB+@d;K+!w?bB40b{*Ivsp*J2~J@RU|?JJo@b(zTS?|I%z?3#P6q zW}cr7%jlB6tb&vB%eXVv_Sm@$EO%zaHmvS-S@;oh+;NmQ*)N;2L$#-XM(WO)B+wQv zk?Z;dt*cDMn9B2yqIypqecbr_jx@3-5Sd z=p)O@t7?vQ2#9S}{HQwxluCIi8>cj!$E{l5Hf*U}jI8s|O35FtYBveU^HK2G{>|S; zg|zyJ!7Em&uBDf-oA$TyC-uy$o)D+eKgT}O##Zp5Ra^N^pET#6f39`Iui<95V1C~F oe-+%^etYL1N^bQc=Pb3ET{ll}6ugoV{|*4>;p^UdF#OVg06PXI^8f$< literal 0 HcmV?d00001 diff --git a/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f76308bbfd82105bdffeeb85286cfa3803866674 GIT binary patch literal 2011 zcmY+Ec{r2{8^&LbH9FQ5S&9-)GWOjN%4EqPLsE7jnqxoIq%0MRbHs^~Ln;X=k|oEn zCKY9uglbarE;D2H{hM=r-#_1VJ@@l_?)(4yx$5tCcfr z^JK46kdZs6Wdj*|zz4iQ0~cy^7X4y5v$BDCrCs=K^*^Fkg^BoYbf4DR?8qpX$^oCNN6rsr31UW^DJgulGTy4yyL&q17zA@0Xv zOJ9z!YjsHc8zaaSSAFw;~@t$(vacY>>!)G07LR!JI`)Tj(0n}eW3NIR^lQJJun-)7=D5sNK=$;{gi zVOxLbmqP;LcgWbCcA<>b{EVbw#hd$p915pKrqeH1ftuFLx@OMbV~Eo+Xpbv*d{Vec zM_h0MghGwW0r$94!hfX~SA)BpXjxZSjgLVc2lmq!+`(6@`WEic1heJ=r+<{)@q(67 z#A;}TOgt#KGxUNA*v6kv`~h40A+9*a_1o;$=b)x7`DiR>ctS|sgzW=pnOB@nvp zeByWVkw{R(ibg17Kj{N^Si?3)xx=po-$_Cin;MhFy4OxpH6y8+vmf{H7FS>thQGKX z;&7;pFO7n#-f=mj@mJAblwlmH@=R8fdy5bynhfJ~(v zOC)WxWVdv2Cud;CAbQ~qa4#A(KqC$Tl#pcp*A3X*8$w~YQ*$IOTUvS%-Boy*j))}QWWNbVoC=oV2 zEbc|N*W(^BB+~=@0*RY4#-a6MClTd+*hAngU-3h1^e1>Z2_NXG4y>g=_pO+nHgvO*uL{;W;yF^DM>o-z zlUFJ!+jY;VQ6j?kbHk*V?^EWH4Th2b^-<1t`iplTKq=qq<;q+v+2!TT#OQfm zPcq>??wH=sbUhTleA-DSJjzT_`)IDrshlO^+Zi0)+f*@XeYfA2%87^Oo#XV?KE-d2 zm$%i`=ps*K@RahCxbW7IVig1Ty`@hnP4CTT7E0x1QTX=GGcBt7+OC~=P&5{{-wwZM7*bg;YvfL&hni5#dcCn%dyZNhRs_#9I2;# z-LJ=eaHPr6ST1h;p%Jb+SUP`Z1{oS0oq3tRHmzxg!^TZEC}+=~*?;c&oJ8KEjW?r1 zv?f^~_uFcIVP$R-(B7v3o3N?@{EDR0IkXgEmx2;{vA5Fh%&WoS{tfnMWSWgG!KgzE zFdG?Ga*udzke!V+j%b2SQ9Zh?X;+3b%GTFkzV*;P$(Pb4Ov~ie6@TuM5FKh&0~}jQ z+EdQEs{>{~C{`MTIAe)_VkSC5x=Xfps^AyvhI?M$DeKct8k&8kEjvKb|7mbf%~MI~ z$0rn*V^zt`f1(hQHPsu`j-2lWRoZK0orjd?KI$Tw*H1r_PQU(8NO|p_RohWI6j_C% zZ&4=9-TTdA0hE){|L16;Kn8BBNKqPD?N<5xciev3dIU2^xbrh|Ki%Ld=b+cS9ku%u z2SVGvY+5ba+$!8&Vj8xj>f|%qjEPE_N+zrj43&HmzGSM{?&}l$fFVFh!>#sNK_iRR3X+J)D@E{`}uj6aTWrv~Iwx2yFQQVBh|Q#k74 zC1QO)zio}76kB!vQFPy_qmP@u-3nIjPUuz`Skg;Mq9nh~G9iP~gCn<25S{TBJi#5W z3;jen1vRblPCmZ9niqYikX)r8ZR?zl@w`>%*N!fekCk&dpq%pIs!lVXxDXAU9T5FK zCZIM%4qdTMb1S=q7CGF;p47LfeuAGt{u=*89bd(URd3-rf7V)f{-w?xyN;QYL><`k ne-#vMyS?L2W%mZ5OSby#&YPz<3t!2Ke+Pi^^z&#t7;))8h5RTq literal 0 HcmV?d00001 diff --git a/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9be3e3b35b814d8405edf35d09f68e1e2daeb0f9 GIT binary patch literal 4352 zcmd5=i9ZzD7auRX7(z0P$-ae0wqi_U35m%TEwa6`gdrx&F!qEPTS|y3pY^tKumu33lmLLZBmiKaJr%bK0HFQ`0MH<06^H@+8pi_F}X2~&O5yn)3HV08E9c`9&-0<5;`=`@s?ZuIHRRpx9Vq` z@Zp7MiLdvmmsWPT$(!9OB*!{XU}V|dZ^HG$7VnMocnTN_;P_HNe{KJgyWZ;*SdRR&=Vosb@tup zB{iCA(isI+Fq6~tq!QoFGZqP_FK6SD?G=1I#s2?TS~U-E^1}SegS`pk#htxOfi@t2 zUZ9y=yqX4FF*oZm8QY863XMFtE%P8Ux`$(k=hDP!1)9g^sDhejqJt;G_^lkX3MHn( z)rKuz>sepp?tweIypek3Syzu+^S}0V38xoff{EpBFOxu8O3W}d4~oS0aQ^Ry>qs6q z;0IG@h>U;ZFg{qX3+e-whLX|g{Wquhup~Rcp z?)mxvQ=8zoK<%)^h9=Qy$o+#eIgSX$kkKty(H_sb3{zm0fawem(#K%ti$>%7@wsz{ zXI2uI3?WsWbVSLTe&jf&{;&ECfY=z>USY_vper@EMybxbF5@z`JjL9r zSZi*VITtvY_Av_lEk!-Sz5n{$?rzDW@sjoXJZ-}*jn3mgsI8Zr$%!XHHVb7RBfu|5 z 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 literal 0 HcmV?d00001 diff --git a/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..bd3131bbb1f07def5c717aae13b36022078c2c3e GIT binary patch literal 1387 zcmV-x1(f=UP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw0006j zP)t-s?mt)VKUeNQSMESq?Kx8HD@E%eJ?kDi>mWSrCqnHuPwhBS>?uU-C`0WxQ0_un z?K4d48#nDQN$^%{^LL2#ikbC{n)7^(@n3W9Ia2E#IqW7u?m<}YL0Rl7MeQ_A@LF#3 zd5QIlne%&#@mz52HBRj=Nb4Lp^@^DL)YqUsqo?mSfPI#cQvGx275{Nd#HrLgZrT6f`TG6u@$-6$ z>liia88!5WmhVz$>mNJoB0cUtR{PJ@_MxrrLRs^FkL)Eu{qFJho~r5>H10oG??zqx z-SA#=>lroqy2Je0-s>Yi?mJWOP-gLKe(pe5^_Zmiw7%>nLi)|q{psuNI8g03 zPw-f6@KEtj z{pafSl%e>ry6YM?@@;?XAUpZQ%lzWz@nw1RfROGyRr<`*>n1_(M_%z{ck3KE>J%~f zt+(nFGVVB0`NPWm-s0^rO8)ow?mboOB0lXpQ~mDn|NZ^&Q)uo)Tkb|({`dLn6*BKj zV*c~>@nm@Y=IQ?U`S4k8{Nd&Iq_6q8!R#$a?J-L8c!~9mobEeR?@3_%;NM7T}ACiVaT010qNS#tmY3labT3lag+-G2N4000McNliru;0PTM zHy=s5dk_Es0(?nCK~z}7?bzp26G0RJ@XK3Mh)FJIK?zx+C`1oUF4hpNh>{=?MI-j! zv48~&DmE-wQAA_!9eerrj4)#+?cNJ!#?iU=@y+gU-tFDqy*)wD%|wK0|rCfcPzgNF>wA2z(eQOKOV6fcroBSseI zj~ZPfm5PjtG3IuS87ucj*|_nZQZInw@=cgHsV_Hq3QYBL8pg{571QK+Om{hy88fZ3 zX2(;NbE;e-1!MlX^W=mms}6>0<|pQA9cCv13;Pzx$>FS9n4DTvzZl0@-jWncjx0^h zH3T_c*|Oy_DORjpgsv>~)=OAr{tX+c*rv@}5X{aishGUA2*LE* z$dUOKi9TQfV~PsR>lchlc;kZK(=+t3|w zn2H@~#dZKRS5vX0$FRK#HSXgytIbk?R^|+zpkXJg2=B8~j?)w?a>fQY##`Dc*x7So z0tVvwV%)mWkuonW#xD9UVbcPWkb}iMfbu*TveRvR_~WXFO#166|0002ovPDHLkV1n)6wUGb- literal 0 HcmV?d00001 diff --git a/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b813b5efcb456b91bf5f6a7a96ef4ab048b39278 GIT binary patch literal 3680 zcmd57>w25%+3q|z+*rs-ay7$($~tt4giRe2LO^%0DvQgC}{-%K&b-&YhC~VgrPtr zw4eoH$k<@>v4KGuoG}hBwI(vysZcAoZ~y>w`X4ck%q5&KgzOP;I}7#&j=z$v$DFn>FKhp%qbP5K;OSufEZ0Hm@^gc5{+?V7p;S&BHoV(=QtO3 zg5BI~P|T$bd1x_*|1YFp&0@u$!pD=q#9^8i)!_s}6XGQDhLk>%4=5tG9HB<&c@=L@ zlMm-)1=66*K?X;*5NR(eE@;lL5|FLET&X4)n6#w+Di z=@sDHZ*AjfKOW z1Lh`Rsx%{PhUKSJs%_uRL{9&J^_(B!o@7(nAAhiMt6<6}@rjcyh<%6~6{PclvfsSb z4XJuChH}X{S_@JP5&8xCA#4IqAf853+3^Y(jPL^C_(T%uWxyI7%K@_JGckEGW)deB z+v%!!IP2n3N+%~|98W_EdY7ag564fBwRt6jLbnI%Wa&q0RY%`dCzoE8chq$R>Qc!a zn9gt;JQB(GOlYCQU+YW(mO3zluV`?H?l;UWrmW!NkVn7Bc6a_fnN%G}TdOXuUzG_Y z8zy{-du@x#E#+WJNNNrP{jB$QpspCXYLmKl#;@9G`xR4VJDU{SKNw~_!Nx>2;8a50 z+p>`0<8KOI4UaAr+`goF_8jI1aM_zgx^gl^mX=UH0&+AIT*!UvNxa@)5hJM5)L3r^l0pKkchh} z=_C1bVyv2AMoa-TftSkpYmzcEV^yGExJM;B7P2LE>-%4!el=oL#4KsO>f~>u)3?^^ zC>21T|4`XZi}G)s?cp8kB#%IKsgn9XsnU6Jyj(M{*6&TKmX_84{NN)8b8jJo{HGIR zbv~1^l9P>R5XidGRnWk=*Yi(gqGiC=&&j2pO8fAq8E3HayXy~~di37z73vE7+9f(w z@yBz@vl3{@dZQINM_>G^N4vAb$GQ4C_ViCSgRiMl_Td_?xQuu4{Euxb?FDRv!aLAk z%e*DuLHZ0D6kUf&$>D1^a$j7pgjff;`Mv@l@AZ_HTH9rV_rWjuSdV$G=sSh12upcIsLO5T;325xO(-p-T;nPke zgthr%>3OM@l`)@JPM+#a-Y#l`Zllf$iel;YmoYk;0qSEy& zOP)+-RH?n>%b5rixv9vp3pD3W2-60?v>2YKfLQcKFT*cogs>t!)DcCplToIqN4Wy$ zHXIUIPeBB0HB!kWOHp4JK@d;w|%fhJ)Pu)Kor{> zBm!+qg-2y>IjI8>&K9&6mus^5k%tOJpF?Iuj2s*Vjs#V>@ULLsv94Li*9b%#vCU|7)dWi>+1s4o;mZLV4-$CF(T(bupgrZ2Oon`)Ks?-tVF7Aug zVtf1j*8&q4I>>3Om{Oa2luVFG5M?1k$pxFuRWS} zr6MR4L9UYZpr3w|bxSMxiMpv3o(_dpki;3}-nTsV=br+^g)&hS-xrclyS&c zUk5)v>kRR@T4*&7n`kY{&)2jI*SyKzmSWs2RHQSoD(S~$ZfO!8`OwZV8B%6&n z`DPjGKL;K8DrTY0B1$i5+}DifJd_)PjefgtPpZncp$D6kY`-!lpF(K=xM%%V(w0?MApA?hyfaO@8hn$!mS1N&PT9M zok@5-F!qFg=(y(r!Qg5{j>me5LK!cwBMlMdNcA*(U#E(&w|26O3`PvKoDL~$S@qq;mK6gaouK>1$2GLf$)byeuvt?aZ`rz*J z9`kLI*@Hq~0f`ma*{Gx+79v+r>$>6H9br2e){Waqr(dZqpA zN6Ws2P9SZPpy$23Et8YSV{QHLc+_9|y5F43#BgGd`Kk8*?-4 z&hR}=Opq7S^*Br2TsQGuAoP4SX=6={G8jz3=O~>gmX3Sd60&`eIm!#0x4Q1!mPe69 zz#SXm#4O=$L|m9Y3$O8m<6{#qU0vz509$jH_jGobUHpT_d65VIK6`Krdnnf23;jR49_@1g literal 0 HcmV?d00001 diff --git a/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..386f05564d2d95ab9a10676574be5fbe6d187c48 GIT binary patch literal 4033 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 literal 0 HcmV?d00001 diff --git a/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@3x-1.png b/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@3x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..043aace3dae9d5a14c09489b712a6e4d42f505b9 GIT binary patch literal 1423 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 G*#80bj#(Q3 literal 0 HcmV?d00001 diff --git a/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-98x98@2x.png b/Sample/OCKSample/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-98x98@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e0d2b55ca305e1b4a2e3fc57706007a00715f0dc GIT binary patch literal 4305 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 OCKCarePlanActivity { // Create a weekly schedule. - let startDate = NSDateComponents(year: 2016, month: 01, day: 01) - let schedule = OCKCareSchedule.weeklyScheduleWithStartDate(startDate, occurrencesOnEachDay: [1, 1, 1, 1, 1, 1, 1]) + let startDate = DateComponents(year: 2016, month: 01, day: 01) + let schedule = OCKCareSchedule.weeklySchedule(withStartDate: startDate as DateComponents, occurrencesOnEachDay: [1, 1, 1, 1, 1, 1, 1]) // Get the localized strings to use for the assessment. let title = NSLocalizedString("Pain", comment: "") let summary = NSLocalizedString("Lower Back", comment: "") - let activity = OCKCarePlanActivity.assessmentWithIdentifier( - activityType.rawValue, + let activity = OCKCarePlanActivity.assessment( + withIdentifier: activityType.rawValue, groupIdentifier: nil, title: title, text: summary, - tintColor: Colors.Blue.color, + tintColor: Colors.blue.color, resultResettable: true, schedule: schedule, userInfo: nil @@ -83,7 +83,7 @@ struct BackPain: Assessment { ) let questionStep = ORKQuestionStep(identifier: activityType.rawValue, title: question, answer: answerFormat) - questionStep.optional = false + questionStep.isOptional = false // Create an ordered task with a single question. let task = ORKOrderedTask(identifier: activityType.rawValue, steps: [questionStep]) diff --git a/Sample/OCKSample/BloodGlucose.swift b/Sample/OCKSample/BloodGlucose.swift index 20c735f06..5369f0bfb 100644 --- a/Sample/OCKSample/BloodGlucose.swift +++ b/Sample/OCKSample/BloodGlucose.swift @@ -38,23 +38,23 @@ import CareKit struct BloodGlucose: Assessment { // MARK: Activity - let activityType: ActivityType = .BloodGlucose + let activityType: ActivityType = .bloodGlucose func carePlanActivity() -> OCKCarePlanActivity { // Create a weekly schedule. - let startDate = NSDateComponents(year: 2016, month: 01, day: 01) - let schedule = OCKCareSchedule.weeklyScheduleWithStartDate(startDate, occurrencesOnEachDay: [1, 1, 1, 1, 1, 1, 1]) + let startDate = DateComponents(year: 2016, month: 01, day: 01) + let schedule = OCKCareSchedule.weeklySchedule(withStartDate: startDate as DateComponents, occurrencesOnEachDay: [1, 1, 1, 1, 1, 1, 1]) // Get the localized strings to use for the assessment. let title = NSLocalizedString("Blood Glucose", comment: "") let summary = NSLocalizedString("After dinner", comment: "") - let activity = OCKCarePlanActivity.assessmentWithIdentifier( - activityType.rawValue, + let activity = OCKCarePlanActivity.assessment( + withIdentifier: activityType.rawValue, groupIdentifier: nil, title: title, text: summary, - tintColor: Colors.Purple.color, + tintColor: Colors.purple.color, resultResettable: false, schedule: schedule, userInfo: nil @@ -67,14 +67,14 @@ struct BloodGlucose: Assessment { func task() -> ORKTask { // Get the localized strings to use for the task. - let quantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBloodGlucose)! - let unit = HKUnit(fromString: "mg/dL") - let answerFormat = ORKHealthKitQuantityTypeAnswerFormat(quantityType: quantityType, unit: unit, style: .Decimal) + let quantityType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodGlucose)! + let unit = HKUnit(from: "mg/dL") + let answerFormat = ORKHealthKitQuantityTypeAnswerFormat(quantityType: quantityType, unit: unit, style: .decimal) // Create a question. let title = NSLocalizedString("Input your blood glucose", comment: "") let questionStep = ORKQuestionStep(identifier: activityType.rawValue, title: title, answer: answerFormat) - questionStep.optional = false + questionStep.isOptional = false // Create an ordered task with a single question. let task = ORKOrderedTask(identifier: activityType.rawValue, steps: [questionStep]) diff --git a/Sample/OCKSample/BuildInsightsOperation.swift b/Sample/OCKSample/BuildInsightsOperation.swift index 851713005..779fcbd21 100644 --- a/Sample/OCKSample/BuildInsightsOperation.swift +++ b/Sample/OCKSample/BuildInsightsOperation.swift @@ -30,7 +30,7 @@ import CareKit -class BuildInsightsOperation: NSOperation { +class BuildInsightsOperation: Operation { // MARK: Properties @@ -38,13 +38,13 @@ class BuildInsightsOperation: NSOperation { var backPainEvents: DailyEvents? - private(set) var insights = [OCKInsightItem.emptyInsightsMessage()] + fileprivate(set) var insights = [OCKInsightItem.emptyInsightsMessage()] // MARK: NSOperation override func main() { // Do nothing if the operation has been cancelled. - guard !cancelled else { return } + guard !isCancelled else { return } // Create an array of insights. var newInsights = [OCKInsightItem]() @@ -70,26 +70,26 @@ class BuildInsightsOperation: NSOperation { guard let medicationEvents = medicationEvents else { return nil } // Determine the start date for the previous week. - let calendar = NSCalendar.currentCalendar() - let now = NSDate() + let calendar = Calendar.current + let now = Date() - let components = NSDateComponents() + var components = DateComponents() components.day = -7 - let startDate = calendar.weekDatesForDate(calendar.dateByAddingComponents(components, toDate: now, options: [])!).start + let startDate = calendar.weekDatesForDate(calendar.date(byAdding: components as DateComponents, to: now)!).start var totalEventCount = 0 var completedEventCount = 0 for offset in 0..<7 { components.day = offset - let dayDate = calendar.dateByAddingComponents(components, toDate: startDate, options: [])! - let dayComponents = NSDateComponents(date: dayDate, calendar: calendar) + let dayDate = calendar.date(byAdding: components as DateComponents, to: startDate)! + let dayComponents = calendar.dateComponents([.year, .month, .day, .era], from: dayDate) let eventsForDay = medicationEvents[dayComponents] totalEventCount += eventsForDay.count for event in eventsForDay { - if event.state == .Completed { + if event.state == .completed { completedEventCount += 1 } } @@ -101,35 +101,35 @@ class BuildInsightsOperation: NSOperation { let medicationAdherence = Float(completedEventCount) / Float(totalEventCount) // Create an `OCKMessageItem` describing medical adherence. - let percentageFormatter = NSNumberFormatter() - percentageFormatter.numberStyle = .PercentStyle - let formattedAdherence = percentageFormatter.stringFromNumber(medicationAdherence)! + let percentageFormatter = NumberFormatter() + percentageFormatter.numberStyle = .percent + let formattedAdherence = percentageFormatter.string(from: NSNumber(value: medicationAdherence))! - let insight = OCKMessageItem(title: "Medication Adherence", text: "Your medication adherence was \(formattedAdherence) last week.", tintColor: Colors.Pink.color, messageType: .Tip) + let insight = OCKMessageItem(title: "Medication Adherence", text: "Your medication adherence was \(formattedAdherence) last week.", tintColor: Colors.pink.color, messageType: .tip) return insight } func createBackPainInsight() -> OCKInsightItem? { // Make sure there are events to parse. - guard let medicationEvents = medicationEvents, backPainEvents = backPainEvents else { return nil } + guard let medicationEvents = medicationEvents, let backPainEvents = backPainEvents else { return nil } // Determine the date to start pain/medication comparisons from. - let calendar = NSCalendar.currentCalendar() - let components = NSDateComponents() + let calendar = Calendar.current + var components = DateComponents() components.day = -7 - let startDate = calendar.dateByAddingComponents(components, toDate: NSDate(), options: [])! + let startDate = calendar.date(byAdding: components as DateComponents, to: Date())! // Create formatters for the data. - let dayOfWeekFormatter = NSDateFormatter() + let dayOfWeekFormatter = DateFormatter() dayOfWeekFormatter.dateFormat = "E" - let shortDateFormatter = NSDateFormatter() - shortDateFormatter.dateFormat = NSDateFormatter.dateFormatFromTemplate("Md", options: 0, locale: shortDateFormatter.locale) + let shortDateFormatter = DateFormatter() + shortDateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "Md", options: 0, locale: shortDateFormatter.locale) - let percentageFormatter = NSNumberFormatter() - percentageFormatter.numberStyle = .PercentStyle + let percentageFormatter = NumberFormatter() + percentageFormatter.numberStyle = .percent /* Loop through 7 days, collecting medication adherance and pain scores @@ -145,11 +145,11 @@ class BuildInsightsOperation: NSOperation { for offset in 0..<7 { // Determine the day to components. components.day = offset - let dayDate = calendar.dateByAddingComponents(components, toDate: startDate, options: [])! - let dayComponents = NSDateComponents(date: dayDate, calendar: calendar) + let dayDate = calendar.date(byAdding: components as DateComponents, to: startDate)! + let dayComponents = calendar.dateComponents([.year, .month, .day, .era], from: dayDate) // Store the pain result for the current day. - if let result = backPainEvents[dayComponents].first?.result, score = Int(result.valueString) where score > 0 { + if let result = backPainEvents[dayComponents].first?.result, let score = Int(result.valueString) , score > 0 { painValues.append(score) painLabels.append(result.valueString) } @@ -160,25 +160,25 @@ class BuildInsightsOperation: NSOperation { // Store the medication adherance value for the current day. let medicationEventsForDay = medicationEvents[dayComponents] - if let adherence = percentageEventsCompleted(medicationEventsForDay) where adherence > 0.0 { + if let adherence = percentageEventsCompleted(medicationEventsForDay) , adherence > 0.0 { // Scale the adherance to the same 0-10 scale as pain values. let scaledAdeherence = adherence * 10.0 medicationValues.append(scaledAdeherence) - medicationLabels.append(percentageFormatter.stringFromNumber(adherence)!) + medicationLabels.append(percentageFormatter.string(from: NSNumber(value: adherence))!) } else { medicationValues.append(0.0) medicationLabels.append(NSLocalizedString("N/A", comment: "")) } - axisTitles.append(dayOfWeekFormatter.stringFromDate(dayDate)) - axisSubtitles.append(shortDateFormatter.stringFromDate(dayDate)) + axisTitles.append(dayOfWeekFormatter.string(from: dayDate)) + axisSubtitles.append(shortDateFormatter.string(from: dayDate)) } // Create a `OCKBarSeries` for each set of data. - let painBarSeries = OCKBarSeries(title: "Pain", values: painValues, valueLabels: painLabels, tintColor: Colors.Blue.color) - let medicationBarSeries = OCKBarSeries(title: "Medication Adherence", values: medicationValues, valueLabels: medicationLabels, tintColor: Colors.LightBlue.color) + let painBarSeries = OCKBarSeries(title: "Pain", values: painValues as [NSNumber], valueLabels: painLabels, tintColor: Colors.blue.color) + let medicationBarSeries = OCKBarSeries(title: "Medication Adherence", values: medicationValues as [NSNumber], valueLabels: medicationLabels, tintColor: Colors.lightBlue.color) /* Add the series to a chart, specifing the scale to use for the chart @@ -186,7 +186,7 @@ class BuildInsightsOperation: NSOperation { */ let chart = OCKBarChart(title: "Back Pain", text: nil, - tintColor: Colors.Blue.color, + tintColor: Colors.blue.color, axisTitles: axisTitles, axisSubtitles: axisSubtitles, dataSeries: [painBarSeries, medicationBarSeries], @@ -200,11 +200,11 @@ class BuildInsightsOperation: NSOperation { For a given array of `OCKCarePlanEvent`s, returns the percentage that are marked as completed. */ - private func percentageEventsCompleted(events: [OCKCarePlanEvent]) -> Float? { + fileprivate func percentageEventsCompleted(_ events: [OCKCarePlanEvent]) -> Float? { guard !events.isEmpty else { return nil } let completedCount = events.filter({ event in - event.state == .Completed + event.state == .completed }).count return Float(completedCount) / Float(events.count) @@ -216,9 +216,9 @@ class BuildInsightsOperation: NSOperation { extension adds a method to return the first element that matches the day specified by the supplied `NSDateComponents`. */ -extension SequenceType where Generator.Element: OCKCarePlanEvent { +extension Sequence where Iterator.Element: OCKCarePlanEvent { - func eventForDay(dayComponents: NSDateComponents) -> Generator.Element? { + func eventForDay(_ dayComponents: NSDateComponents) -> Iterator.Element? { for event in self where event.date.year == dayComponents.year && event.date.month == dayComponents.month && diff --git a/Sample/OCKSample/CarePlanStoreManager.swift b/Sample/OCKSample/CarePlanStoreManager.swift index 388a349f8..deac36668 100644 --- a/Sample/OCKSample/CarePlanStoreManager.swift +++ b/Sample/OCKSample/CarePlanStoreManager.swift @@ -45,18 +45,18 @@ class CarePlanStoreManager: NSObject { return insightsBuilder.insights } - private let insightsBuilder: InsightsBuilder + fileprivate let insightsBuilder: InsightsBuilder // MARK: Initialization - private override init() { + fileprivate override init() { // Determine the file URL for the store. - let searchPaths = NSSearchPathForDirectoriesInDomains(.ApplicationSupportDirectory, .UserDomainMask, true) + let searchPaths = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true) let applicationSupportPath = searchPaths[0] - let persistenceDirectoryURL = NSURL(fileURLWithPath: applicationSupportPath) + let persistenceDirectoryURL = URL(fileURLWithPath: applicationSupportPath) - if !NSFileManager.defaultManager().fileExistsAtPath(persistenceDirectoryURL.absoluteString, isDirectory: nil) { - try! NSFileManager.defaultManager().createDirectoryAtURL(persistenceDirectoryURL, withIntermediateDirectories: true, attributes: nil) + if !FileManager.default.fileExists(atPath: persistenceDirectoryURL.absoluteString, isDirectory: nil) { + try! FileManager.default.createDirectory(at: persistenceDirectoryURL, withIntermediateDirectories: true, attributes: nil) } // Create the store. @@ -81,7 +81,7 @@ class CarePlanStoreManager: NSObject { func updateInsights() { insightsBuilder.updateInsights { [weak self] completed, newInsights in // If new insights have been created, notifiy the delegate. - guard let storeManager = self, newInsights = newInsights where completed else { return } + guard let storeManager = self, let newInsights = newInsights , completed else { return } storeManager.delegate?.carePlanStoreManager(storeManager, didUpdateInsights: newInsights) } } @@ -90,11 +90,11 @@ class CarePlanStoreManager: NSObject { extension CarePlanStoreManager: OCKCarePlanStoreDelegate { - func carePlanStoreActivityListDidChange(store: OCKCarePlanStore) { + func carePlanStoreActivityListDidChange(_ store: OCKCarePlanStore) { updateInsights() } - func carePlanStore(store: OCKCarePlanStore, didReceiveUpdateOfEvent event: OCKCarePlanEvent) { + func carePlanStore(_ store: OCKCarePlanStore, didReceiveUpdateOf event: OCKCarePlanEvent) { updateInsights() } } @@ -103,6 +103,6 @@ extension CarePlanStoreManager: OCKCarePlanStoreDelegate { protocol CarePlanStoreManagerDelegate: class { - func carePlanStoreManager(manager: CarePlanStoreManager, didUpdateInsights insights: [OCKInsightItem]) + func carePlanStoreManager(_ manager: CarePlanStoreManager, didUpdateInsights insights: [OCKInsightItem]) -} \ No newline at end of file +} diff --git a/Sample/OCKSample/Colors.swift b/Sample/OCKSample/Colors.swift index bcc80f144..b1e05f74d 100644 --- a/Sample/OCKSample/Colors.swift +++ b/Sample/OCKSample/Colors.swift @@ -32,29 +32,29 @@ import UIKit enum Colors { - case Red, Green, Blue, LightBlue, Pink, Purple, Yellow + case red, green, blue, lightBlue, pink, purple, yellow var color: UIColor { switch self { - case .Red: + case .red: return UIColor(red: 0xEF / 255.0, green: 0x44 / 255.0, blue: 0x5B / 255.0, alpha: 1.0) - case .Green: + case .green: return UIColor(red: 0x8D / 255.0, green: 0xC6 / 255.0, blue: 0x3F / 255.0, alpha: 1.0) - case .Blue: + case .blue: return UIColor(red: 0x3E / 255.0, green: 0xA1 / 255.0, blue: 0xEE / 255.0, alpha: 1.0) - case .LightBlue: + case .lightBlue: return UIColor(red: 0x9C / 255.0, green: 0xCF / 255.0, blue: 0xF8 / 255.0, alpha: 1.0) - case .Pink: + case .pink: return UIColor(red: 0xF2 / 255.0, green: 0x6D / 255.0, blue: 0x7D / 255.0, alpha: 1.0) - case .Purple: + case .purple: return UIColor(red: 0x9B / 255.0, green: 0x59 / 255.0, blue: 0xB6 / 255.0, alpha: 1.0) - case .Yellow: + case .yellow: return UIColor(red: 0xF1 / 255.0, green: 0xDF / 255.0, blue: 0x15 / 255.0, alpha: 1.0) } } diff --git a/Sample/OCKSample/HamstringStretch.swift b/Sample/OCKSample/HamstringStretch.swift index 9cdb1ada8..ce7654d02 100644 --- a/Sample/OCKSample/HamstringStretch.swift +++ b/Sample/OCKSample/HamstringStretch.swift @@ -37,12 +37,12 @@ import CareKit struct HamstringStretch: Activity { // MARK: Activity - let activityType: ActivityType = .HamstringStretch + let activityType: ActivityType = .hamstringStretch func carePlanActivity() -> OCKCarePlanActivity { // Create a weekly schedule. - let startDate = NSDateComponents(year: 2016, month: 01, day: 01) - let schedule = OCKCareSchedule.weeklyScheduleWithStartDate(startDate, occurrencesOnEachDay: [2, 1, 1, 1, 1, 1, 2]) + let startDate = DateComponents(year: 2016, month: 01, day: 01) + let schedule = OCKCareSchedule.weeklySchedule(withStartDate: startDate as DateComponents, occurrencesOnEachDay: [2, 1, 1, 1, 1, 1, 2]) // Get the localized strings to use for the activity. let title = NSLocalizedString("Hamstring Stretch", comment: "") @@ -50,12 +50,12 @@ struct HamstringStretch: Activity { let instructions = NSLocalizedString("Gentle hamstring stretches on both legs.", comment: "") // Create the intervention activity. - let activity = OCKCarePlanActivity.interventionWithIdentifier( - activityType.rawValue, + let activity = OCKCarePlanActivity.intervention( + withIdentifier: activityType.rawValue, groupIdentifier: nil, title: title, text: summary, - tintColor: Colors.Blue.color, + tintColor: Colors.blue.color, instructions: instructions, imageURL: nil, schedule: schedule, diff --git a/Sample/OCKSample/HealthSampleBuilder.swift b/Sample/OCKSample/HealthSampleBuilder.swift index e0ddf62b1..ebec2c9a9 100644 --- a/Sample/OCKSample/HealthSampleBuilder.swift +++ b/Sample/OCKSample/HealthSampleBuilder.swift @@ -39,7 +39,7 @@ protocol HealthSampleBuilder { var unit: HKUnit { get } - func buildSampleWithTaskResult(result: ORKTaskResult) -> HKQuantitySample + func buildSampleWithTaskResult(_ result: ORKTaskResult) -> HKQuantitySample - func localizedUnitForSample(sample: HKQuantitySample) -> String + func localizedUnitForSample(_ sample: HKQuantitySample) -> String } diff --git a/Sample/OCKSample/InsightsBuilder.swift b/Sample/OCKSample/InsightsBuilder.swift index 5175b566c..74d8f06cf 100644 --- a/Sample/OCKSample/InsightsBuilder.swift +++ b/Sample/OCKSample/InsightsBuilder.swift @@ -33,11 +33,11 @@ import CareKit class InsightsBuilder { /// An array if `OCKInsightItem` to show on the Insights view. - private(set) var insights = [OCKInsightItem.emptyInsightsMessage()] + fileprivate(set) var insights = [OCKInsightItem.emptyInsightsMessage()] - private let carePlanStore: OCKCarePlanStore + fileprivate let carePlanStore: OCKCarePlanStore - private let updateOperationQueue = NSOperationQueue() + fileprivate let updateOperationQueue = OperationQueue() required init(carePlanStore: OCKCarePlanStore) { self.carePlanStore = carePlanStore @@ -47,7 +47,7 @@ class InsightsBuilder { Enqueues `NSOperation`s to query the `OCKCarePlanStore` and update the `insights` property. */ - func updateInsights(completion: ((Bool, [OCKInsightItem]?) -> Void)?) { + func updateInsights(_ completion: ((Bool, [OCKInsightItem]?) -> Void)?) { // Cancel any in-progress operations. updateOperationQueue.cancelAllOperations() @@ -60,7 +60,7 @@ class InsightsBuilder { */ let medicationEventsOperation = QueryActivityEventsOperation(store: carePlanStore, - activityIdentifier: ActivityType.TakeMedication.rawValue, + activityIdentifier: ActivityType.takeMedication.rawValue, startDate: queryDateRange.start, endDate: queryDateRange.end) @@ -69,7 +69,7 @@ class InsightsBuilder { current weeks' `BackPain` assessment. */ let backPainEventsOperation = QueryActivityEventsOperation(store: carePlanStore, - activityIdentifier: ActivityType.BackPain.rawValue, + activityIdentifier: ActivityType.backPain.rawValue, startDate: queryDateRange.start, endDate: queryDateRange.end) @@ -83,7 +83,7 @@ class InsightsBuilder { Create an operation to aggregate the data from query operations into the `BuildInsightsOperation`. */ - let aggregateDataOperation = NSBlockOperation { + let aggregateDataOperation = BlockOperation { // Copy the queried data from the query operations to the `BuildInsightsOperation`. buildInsightsOperation.medicationEvents = medicationEventsOperation.dailyEvents buildInsightsOperation.backPainEvents = backPainEventsOperation.dailyEvents @@ -94,11 +94,11 @@ class InsightsBuilder { new insights and call the completion block passed to this method. */ buildInsightsOperation.completionBlock = { [unowned buildInsightsOperation] in - let completed = !buildInsightsOperation.cancelled + let completed = !buildInsightsOperation.isCancelled let newInsights = buildInsightsOperation.insights // Call the completion block on the main queue. - NSOperationQueue.mainQueue().addOperationWithBlock { + OperationQueue.main.addOperation { if completed { completion?(true, newInsights) } @@ -124,15 +124,15 @@ class InsightsBuilder { ], waitUntilFinished: false) } - private func calculateQueryDateRange() -> (start: NSDateComponents, end: NSDateComponents) { - let calendar = NSCalendar.currentCalendar() - let now = NSDate() + fileprivate func calculateQueryDateRange() -> (start: DateComponents, end: DateComponents) { + let calendar = Calendar.current + let now = Date() let currentWeekRange = calendar.weekDatesForDate(now) - let previousWeekRange = calendar.weekDatesForDate(currentWeekRange.start.dateByAddingTimeInterval(-1)) + let previousWeekRange = calendar.weekDatesForDate(currentWeekRange.start.addingTimeInterval(-1)) - let queryRangeStart = NSDateComponents(date: previousWeekRange.start, calendar: calendar) - let queryRangeEnd = NSDateComponents(date: now, calendar: calendar) + let queryRangeStart = calendar.dateComponents([.year, .month, .day, .era], from: previousWeekRange.start) + let queryRangeEnd = calendar.dateComponents([.year, .month, .day, .era], from: now) return (start: queryRangeStart, end: queryRangeEnd) } @@ -141,5 +141,5 @@ class InsightsBuilder { protocol InsightsBuilderDelegate: class { - func insightsBuilder(insightsBuilder: InsightsBuilder, didUpdateInsights insights: [OCKInsightItem]) + func insightsBuilder(_ insightsBuilder: InsightsBuilder, didUpdateInsights insights: [OCKInsightItem]) } diff --git a/Sample/OCKSample/Mood.swift b/Sample/OCKSample/Mood.swift index d015fb412..c78e936ca 100644 --- a/Sample/OCKSample/Mood.swift +++ b/Sample/OCKSample/Mood.swift @@ -38,22 +38,22 @@ import CareKit struct Mood: Assessment { // MARK: Activity - let activityType: ActivityType = .Mood + let activityType: ActivityType = .mood func carePlanActivity() -> OCKCarePlanActivity { // Create a weekly schedule. - let startDate = NSDateComponents(year: 2016, month: 01, day: 01) - let schedule = OCKCareSchedule.weeklyScheduleWithStartDate(startDate, occurrencesOnEachDay: [1, 1, 1, 1, 1, 1, 1]) + let startDate = DateComponents(year: 2016, month: 01, day: 01) + let schedule = OCKCareSchedule.weeklySchedule(withStartDate: startDate as DateComponents, occurrencesOnEachDay: [1, 1, 1, 1, 1, 1, 1]) // Get the localized strings to use for the assessment. let title = NSLocalizedString("Mood", comment: "") - let activity = OCKCarePlanActivity.assessmentWithIdentifier( - activityType.rawValue, + let activity = OCKCarePlanActivity.assessment( + withIdentifier: activityType.rawValue, groupIdentifier: nil, title: title, text: nil, - tintColor: Colors.Green.color, + tintColor: Colors.green.color, resultResettable: false, schedule: schedule, userInfo: nil @@ -82,7 +82,7 @@ struct Mood: Assessment { ) let questionStep = ORKQuestionStep(identifier: activityType.rawValue, title: question, answer: answerFormat) - questionStep.optional = false + questionStep.isOptional = false // Create an ordered task with a single question. let task = ORKOrderedTask(identifier: activityType.rawValue, steps: [questionStep]) diff --git a/Sample/OCKSample/NSCalendar+Dates.swift b/Sample/OCKSample/NSCalendar+Dates.swift index 2c5027282..b05fc0bb8 100644 --- a/Sample/OCKSample/NSCalendar+Dates.swift +++ b/Sample/OCKSample/NSCalendar+Dates.swift @@ -30,17 +30,17 @@ import Foundation -extension NSCalendar { +extension Calendar { /** Returns a tuple containing the start and end dates for the week that the specified date falls in. */ - func weekDatesForDate(date: NSDate) -> (start: NSDate, end: NSDate) { - var interval: NSTimeInterval = 0 - var start: NSDate? - rangeOfUnit(.WeekOfYear, startDate: &start, interval: &interval, forDate: date) - let end = start!.dateByAddingTimeInterval(interval) + func weekDatesForDate(_ date: Date) -> (start: Date, end: Date) { + var interval: TimeInterval = 0 + var start: Date = Date() + _ = dateInterval(of: .weekOfYear, start: &start, interval: &interval, for: date) + let end = start.addingTimeInterval(interval) - return (start!, end) + return (start as Date, end as Date) } } diff --git a/Sample/OCKSample/OCKInsightItem+EmptyMessage.swift b/Sample/OCKSample/OCKInsightItem+EmptyMessage.swift index 56c8e6304..03931ec78 100644 --- a/Sample/OCKSample/OCKInsightItem+EmptyMessage.swift +++ b/Sample/OCKSample/OCKInsightItem+EmptyMessage.swift @@ -33,6 +33,6 @@ import CareKit extension OCKInsightItem { /// Returns an `OCKInsightItem` to show when no insights have been calculated. static func emptyInsightsMessage() -> OCKInsightItem { - return OCKMessageItem(title: "No Insights", text: "There are no insights to show.", tintColor: Colors.Green.color, messageType: .Tip) + return OCKMessageItem(title: "No Insights", text: "There are no insights to show.", tintColor: Colors.green.color, messageType: .tip) } } diff --git a/Sample/OCKSample/OutdoorWalk.swift b/Sample/OCKSample/OutdoorWalk.swift index 1bde3e0e1..285a43144 100644 --- a/Sample/OCKSample/OutdoorWalk.swift +++ b/Sample/OCKSample/OutdoorWalk.swift @@ -37,25 +37,25 @@ import CareKit struct OutdoorWalk: Activity { // MARK: Activity - let activityType: ActivityType = .OutdoorWalk + let activityType: ActivityType = .outdoorWalk func carePlanActivity() -> OCKCarePlanActivity { // Create a weekly schedule. - let startDate = NSDateComponents(year: 2016, month: 01, day: 01) - let schedule = OCKCareSchedule.weeklyScheduleWithStartDate(startDate, occurrencesOnEachDay: [2, 1, 1, 1, 1, 1, 2]) + let startDate = DateComponents(year: 2016, month: 01, day: 01) + let schedule = OCKCareSchedule.weeklySchedule(withStartDate: startDate as DateComponents, occurrencesOnEachDay: [2, 1, 1, 1, 1, 1, 2]) // Get the localized strings to use for the activity. - let title = NSLocalizedString("Outdoor walk", comment: "") + let title = NSLocalizedString("Outdoor Walk", comment: "") let summary = NSLocalizedString("15 mins", comment: "") let instructions = NSLocalizedString("Take a leisurely walk.", comment: "") // Create the intervention activity. - let activity = OCKCarePlanActivity.interventionWithIdentifier( - activityType.rawValue, + let activity = OCKCarePlanActivity.intervention( + withIdentifier: activityType.rawValue, groupIdentifier: nil, title: title, text: summary, - tintColor: Colors.Purple.color, + tintColor: Colors.purple.color, instructions: instructions, imageURL: nil, schedule: schedule, diff --git a/Sample/OCKSample/QueryActivityEventsOperation.swift b/Sample/OCKSample/QueryActivityEventsOperation.swift index 223508095..9425f470d 100644 --- a/Sample/OCKSample/QueryActivityEventsOperation.swift +++ b/Sample/OCKSample/QueryActivityEventsOperation.swift @@ -30,22 +30,22 @@ import CareKit -class QueryActivityEventsOperation: NSOperation { +class QueryActivityEventsOperation: Operation { // MARK: Properties - private let store: OCKCarePlanStore + fileprivate let store: OCKCarePlanStore - private let activityIdentifier: String + fileprivate let activityIdentifier: String - private let startDate: NSDateComponents + fileprivate let startDate: DateComponents - private let endDate: NSDateComponents + fileprivate let endDate: DateComponents - private(set) var dailyEvents: DailyEvents? + fileprivate(set) var dailyEvents: DailyEvents? // MARK: Initialization - init(store: OCKCarePlanStore, activityIdentifier: String, startDate: NSDateComponents, endDate: NSDateComponents) { + init(store: OCKCarePlanStore, activityIdentifier: String, startDate: DateComponents, endDate: DateComponents) { self.store = store self.activityIdentifier = activityIdentifier self.startDate = startDate @@ -56,7 +56,7 @@ class QueryActivityEventsOperation: NSOperation { override func main() { // Do nothing if the operation has been cancelled. - guard !cancelled else { return } + guard !isCancelled else { return } // Find the activity with the specified identifier in the store. guard let activity = findActivity() else { return } @@ -65,51 +65,51 @@ class QueryActivityEventsOperation: NSOperation { Create a semaphore to wait for the asynchronous call to `enumerateEventsOfActivity` to complete. */ - let semaphore = dispatch_semaphore_create(0) + let semaphore = DispatchSemaphore(value: 0) // Query for events for the activity between the requested dates. self.dailyEvents = DailyEvents() - dispatch_async(dispatch_get_main_queue()) { // [CK] OCKCarePlanStore query methods crash if not called on the main thread - self.store.enumerateEventsOfActivity(activity, startDate: self.startDate, endDate: self.endDate, handler: { event, _ in + DispatchQueue.main.async { // [CK] OCKCarePlanStore query methods crash if not called on the main thread + self.store.enumerateEvents(of: activity, startDate: self.startDate as DateComponents, endDate: self.endDate as DateComponents, handler: { event, _ in if let event = event { self.dailyEvents?[event.date].append(event) } }, completion: { _, _ in // Use the semaphore to signal that the query is complete. - dispatch_semaphore_signal(semaphore) + semaphore.signal() }) } // Wait for the semaphore to be signalled. - dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) + _ = semaphore.wait(timeout: DispatchTime.distantFuture) } // MARK: Convenience - private func findActivity() -> OCKCarePlanActivity? { + fileprivate func findActivity() -> OCKCarePlanActivity? { /* Create a semaphore to wait for the asynchronous call to `activityForIdentifier` to complete. */ - let semaphore = dispatch_semaphore_create(0) + let semaphore = DispatchSemaphore(value: 0) var activity: OCKCarePlanActivity? - dispatch_async(dispatch_get_main_queue()) { // [CK] OCKCarePlanStore query methods crash if not called on the main thread - self.store.activityForIdentifier(self.activityIdentifier) { success, foundActivity, error in + DispatchQueue.main.async { // [CK] OCKCarePlanStore query methods crash if not called on the main thread + self.store.activity(forIdentifier: self.activityIdentifier) { success, foundActivity, error in activity = foundActivity if !success { print(error?.localizedDescription) } // Use the semaphore to signal that the query is complete. - dispatch_semaphore_signal(semaphore) + semaphore.signal() } } // Wait for the semaphore to be signalled. - dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) + _ = semaphore.wait(timeout: DispatchTime.distantFuture) return activity } @@ -120,17 +120,17 @@ class QueryActivityEventsOperation: NSOperation { struct DailyEvents { // MARK: Properties - private var mappedEvents: [NSDateComponents: [OCKCarePlanEvent]] + fileprivate var mappedEvents: [DateComponents: [OCKCarePlanEvent]] var allEvents: [OCKCarePlanEvent] { - return Array(mappedEvents.values.flatten()) + return Array(mappedEvents.values.joined()) } - var allDays: [NSDateComponents] { + var allDays: [DateComponents] { return Array(mappedEvents.keys) } - subscript(day: NSDateComponents) -> [OCKCarePlanEvent] { + subscript(day: DateComponents) -> [OCKCarePlanEvent] { get { if let events = mappedEvents[day] { return events diff --git a/Sample/OCKSample/RootViewController.swift b/Sample/OCKSample/RootViewController.swift index 2b191f028..140433ce6 100644 --- a/Sample/OCKSample/RootViewController.swift +++ b/Sample/OCKSample/RootViewController.swift @@ -31,22 +31,24 @@ import UIKit import CareKit import ResearchKit +import WatchConnectivity class RootViewController: UITabBarController { // MARK: Properties - private let sampleData: SampleData + fileprivate let sampleData: SampleData - private let storeManager = CarePlanStoreManager.sharedCarePlanStoreManager + fileprivate let storeManager = CarePlanStoreManager.sharedCarePlanStoreManager - private var careCardViewController: OCKCareCardViewController! + fileprivate var careCardViewController: OCKCareCardViewController! - private var symptomTrackerViewController: OCKSymptomTrackerViewController! + fileprivate var symptomTrackerViewController: OCKSymptomTrackerViewController! - private var insightsViewController: OCKInsightsViewController! + fileprivate var insightsViewController: OCKInsightsViewController! - private var connectViewController: OCKConnectViewController! + fileprivate var connectViewController: OCKConnectViewController! + fileprivate var watchManager: WatchConnectivityManager? // MARK: Initialization required init?(coder aDecoder: NSCoder) { @@ -67,11 +69,12 @@ class RootViewController: UITabBarController { ] storeManager.delegate = self + watchManager = WatchConnectivityManager(withStore: storeManager.store) } // MARK: Convenience - private func createInsightsViewController() -> OCKInsightsViewController { + fileprivate func createInsightsViewController() -> OCKInsightsViewController { // Create an `OCKInsightsViewController` with sample data. let headerTitle = NSLocalizedString("Weekly Charts", comment: "") let viewController = OCKInsightsViewController(insightItems: storeManager.insights, headerTitle: headerTitle, headerSubtitle: "") @@ -83,7 +86,7 @@ class RootViewController: UITabBarController { return viewController } - private func createCareCardViewController() -> OCKCareCardViewController { + fileprivate func createCareCardViewController() -> OCKCareCardViewController { let viewController = OCKCareCardViewController(carePlanStore: storeManager.store) // Setup the controller's title and tab bar item @@ -93,7 +96,7 @@ class RootViewController: UITabBarController { return viewController } - private func createSymptomTrackerViewController() -> OCKSymptomTrackerViewController { + fileprivate func createSymptomTrackerViewController() -> OCKSymptomTrackerViewController { let viewController = OCKSymptomTrackerViewController(carePlanStore: storeManager.store) viewController.delegate = self @@ -104,7 +107,7 @@ class RootViewController: UITabBarController { return viewController } - private func createConnectViewController() -> OCKConnectViewController { + fileprivate func createConnectViewController() -> OCKConnectViewController { let viewController = OCKConnectViewController(contacts: sampleData.contacts) viewController.delegate = self @@ -121,7 +124,7 @@ class RootViewController: UITabBarController { extension RootViewController: OCKSymptomTrackerViewControllerDelegate { /// Called when the user taps an assessment on the `OCKSymptomTrackerViewController`. - func symptomTrackerViewController(viewController: OCKSymptomTrackerViewController, didSelectRowWithAssessmentEvent assessmentEvent: OCKCarePlanEvent) { + func symptomTrackerViewController(_ viewController: OCKSymptomTrackerViewController, didSelectRowWithAssessmentEvent assessmentEvent: OCKCarePlanEvent) { // Lookup the assessment the row represents. guard let activityType = ActivityType(rawValue: assessmentEvent.activity.identifier) else { return } guard let sampleAssessment = sampleData.activityWithType(activityType) as? Assessment else { return } @@ -130,15 +133,15 @@ extension RootViewController: OCKSymptomTrackerViewControllerDelegate { Check if we should show a task for the selected assessment event based on its state. */ - guard assessmentEvent.state == .Initial || - assessmentEvent.state == .NotCompleted || - (assessmentEvent.state == .Completed && assessmentEvent.activity.resultResettable) else { return } + guard assessmentEvent.state == .initial || + assessmentEvent.state == .notCompleted || + (assessmentEvent.state == .completed && assessmentEvent.activity.resultResettable) else { return } // Show an `ORKTaskViewController` for the assessment's task. - let taskViewController = ORKTaskViewController(task: sampleAssessment.task(), taskRunUUID: nil) + let taskViewController = ORKTaskViewController(task: sampleAssessment.task(), taskRun: nil) taskViewController.delegate = self - presentViewController(taskViewController, animated: true, completion: nil) + present(taskViewController, animated: true, completion: nil) } } @@ -146,19 +149,19 @@ extension RootViewController: OCKSymptomTrackerViewControllerDelegate { extension RootViewController: ORKTaskViewControllerDelegate { - /// Called when the user completes a presented `ORKTaskViewController`. - func taskViewController(taskViewController: ORKTaskViewController, didFinishWithReason reason: ORKTaskViewControllerFinishReason, error: NSError?) { + /// Called with then user completes a presented `ORKTaskViewController`. + func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskViewControllerFinishReason, error: Error?) { defer { - dismissViewControllerAnimated(true, completion: nil) + dismiss(animated: true, completion: nil) } // Make sure the reason the task controller finished is that it was completed. - guard reason == .Completed else { return } + guard reason == .completed else { return } // Determine the event that was completed and the `SampleAssessment` it represents. guard let event = symptomTrackerViewController.lastSelectedAssessmentEvent, - activityType = ActivityType(rawValue: event.activity.identifier), - sampleAssessment = sampleData.activityWithType(activityType) as? Assessment else { return } + let activityType = ActivityType(rawValue: event.activity.identifier), + let sampleAssessment = sampleData.activityWithType(activityType) as? Assessment else { return } // Build an `OCKCarePlanEventResult` that can be saved into the `OCKCarePlanStore`. let carePlanResult = sampleAssessment.buildResultForCarePlanEvent(event, taskResult: taskViewController.result) @@ -171,7 +174,7 @@ extension RootViewController: ORKTaskViewControllerDelegate { // Requst authorization to store the HealthKit sample. let healthStore = HKHealthStore() - healthStore.requestAuthorizationToShareTypes(sampleTypes, readTypes: sampleTypes, completion: { success, _ in + healthStore.requestAuthorization(toShare: sampleTypes, read: sampleTypes, completion: { success, _ in // Check if authorization was granted. if !success { /* @@ -183,7 +186,7 @@ extension RootViewController: ORKTaskViewControllerDelegate { } // Save the HealthKit sample in the HealthKit store. - healthStore.saveObject(sample, withCompletion: { success, _ in + healthStore.save(sample, withCompletion: { success, _ in if success { /* The sample was saved to the HealthKit store. Use it @@ -193,7 +196,7 @@ extension RootViewController: ORKTaskViewControllerDelegate { let healthKitAssociatedResult = OCKCarePlanEventResult( quantitySample: sample, quantityStringFormatter: nil, - displayUnit: healthSampleBuilder.unit, + display: healthSampleBuilder.unit, displayUnitStringKey: healthSampleBuilder.localizedUnitForSample(sample), userInfo: nil ) @@ -219,8 +222,8 @@ extension RootViewController: ORKTaskViewControllerDelegate { // MARK: Convenience - private func completeEvent(event: OCKCarePlanEvent, inStore store: OCKCarePlanStore, withResult result: OCKCarePlanEventResult) { - store.updateEvent(event, withResult: result, state: .Completed) { success, _, error in + fileprivate func completeEvent(_ event: OCKCarePlanEvent, inStore store: OCKCarePlanStore, withResult result: OCKCarePlanEventResult) { + store.update(event, with: result, state: .completed) { success, _, error in if !success { print(error?.localizedDescription) } @@ -228,25 +231,26 @@ extension RootViewController: ORKTaskViewControllerDelegate { } } - +// MARK: OCKConnectViewControllerDelegate extension RootViewController: OCKConnectViewControllerDelegate { /// Called when the user taps a contact in the `OCKConnectViewController`. - func connectViewController(connectViewController: OCKConnectViewController, didSelectShareButtonForContact contact: OCKContact, presentationSourceView sourceView: UIView?) { + func connectViewController(_ connectViewController: OCKConnectViewController, didSelectShareButtonFor contact: OCKContact, presentationSourceView sourceView: UIView?) { let document = sampleData.generateSampleDocument() let activityViewController = UIActivityViewController(activityItems: [document], applicationActivities: nil) - activityViewController.popoverPresentationController?.sourceView = sourceView - presentViewController(activityViewController, animated: true, completion: nil) + present(activityViewController, animated: true, completion: nil) } } +// MARK: CarePlanStoreManagerDelegate + extension RootViewController: CarePlanStoreManagerDelegate { /// Called when the `CarePlanStoreManager`'s insights are updated. - func carePlanStoreManager(manager: CarePlanStoreManager, didUpdateInsights insights: [OCKInsightItem]) { + func carePlanStoreManager(_ manager: CarePlanStoreManager, didUpdateInsights insights: [OCKInsightItem]) { // Update the insights view controller with the new insights. insightsViewController.items = insights } diff --git a/Sample/OCKSample/SampleData.swift b/Sample/OCKSample/SampleData.swift index aa834c5f5..d44de89a5 100644 --- a/Sample/OCKSample/SampleData.swift +++ b/Sample/OCKSample/SampleData.swift @@ -1,21 +1,21 @@ /* Copyright (c) 2016, Apple Inc. All rights reserved. - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - + 3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. No license is granted to the trademarks of the copyright holders even if such marks are included in this software. - + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -32,7 +32,7 @@ import ResearchKit import CareKit class SampleData: NSObject { - + // MARK: Properties /// An array of `Activity`s used in the app. @@ -45,73 +45,73 @@ class SampleData: NSObject { BloodGlucose(), Weight() ] - + /** An array of `OCKContact`s to display on the Connect view. */ let contacts: [OCKContact] = [ - OCKContact(contactType: .CareTeam, + OCKContact(contactType: .careTeam, name: "Dr. Maria Ruiz", relation: "Physician", contactInfoItems:[.phone("888-555-5512"), .sms("888-555-5512"), .email("mruiz2@mac.com")], - tintColor: Colors.Blue.color, + tintColor: Colors.blue.color, monogram: "MR", image: nil), - - OCKContact(contactType: .CareTeam, + + OCKContact(contactType: .careTeam, name: "Bill James", relation: "Nurse", contactInfoItems:[.phone("888-555-5512"), .sms("888-555-5512"), .email("billjames2@mac.com")], - tintColor: Colors.Green.color, + tintColor: Colors.green.color, monogram: nil, image: nil), - - OCKContact(contactType: .Personal, - name: "Tom Van de Clark", + + OCKContact(contactType: .personal, + name: "Tom Clark", relation: "Father", - contactInfoItems:[.phone("888-555-5512"), .sms("888-555-5512"), .facetimeVideo("8885555512", displayString: "888-555-5512")], - tintColor: Colors.Yellow.color, + contactInfoItems:[.phone("888-555-5512"), .sms("888-555-5512"), .facetimeVideo("8885555512", display: "888-555-5512")], + tintColor: Colors.yellow.color, monogram: nil, image: nil) ] - + // MARK: Initialization - + required init(carePlanStore: OCKCarePlanStore) { super.init() // Populate the store with the sample activities. for sampleActivity in activities { let carePlanActivity = sampleActivity.carePlanActivity() - - carePlanStore.addActivity(carePlanActivity) { success, error in + + carePlanStore.add(carePlanActivity) { success, error in if !success { print(error?.localizedDescription) } } } - + } - + // MARK: Convenience - + /// Returns the `Activity` that matches the supplied `ActivityType`. - func activityWithType(type: ActivityType) -> Activity? { + func activityWithType(_ type: ActivityType) -> Activity? { for activity in activities where activity.activityType == type { return activity } - + return nil } - + func generateSampleDocument() -> OCKDocument { let subtitle = OCKDocumentElementSubtitle(subtitle: "First subtitle") - + let paragraph = OCKDocumentElementParagraph(content: "Lorem ipsum dolor sit amet, vim primis noster sententiae ne, et albucius apeirian accusata mea, vim at dicunt laoreet. Eu probo omnes inimicus ius, duo at veritus alienum. Nostrud facilisi id pro. Putant oporteat id eos. Admodum antiopam mel in, at per everti quaeque. Lorem ipsum dolor sit amet, vim primis noster sententiae ne, et albucius apeirian accusata mea, vim at dicunt laoreet. Eu probo omnes inimicus ius, duo at veritus alienum. Nostrud facilisi id pro. Putant oporteat id eos. Admodum antiopam mel in, at per everti quaeque. Lorem ipsum dolor sit amet, vim primis noster sententiae ne, et albucius apeirian accusata mea, vim at dicunt laoreet. Eu probo omnes inimicus ius, duo at veritus alienum. Nostrud facilisi id pro. Putant oporteat id eos. Admodum antiopam mel in, at per everti quaeque.") - + let document = OCKDocument(title: "Sample Document Title", elements: [subtitle, paragraph]) document.pageHeader = "App Name: OCKSample, User Name: John Appleseed" - + return document } } diff --git a/Sample/OCKSample/TakeMedication.swift b/Sample/OCKSample/TakeMedication.swift index 4cfa68453..b4945e187 100644 --- a/Sample/OCKSample/TakeMedication.swift +++ b/Sample/OCKSample/TakeMedication.swift @@ -37,24 +37,24 @@ import CareKit struct TakeMedication: Activity { // MARK: Activity - let activityType: ActivityType = .TakeMedication + let activityType: ActivityType = .takeMedication func carePlanActivity() -> OCKCarePlanActivity { // Create a weekly schedule. - let startDate = NSDateComponents(year: 2016, month: 01, day: 01) - let schedule = OCKCareSchedule.weeklyScheduleWithStartDate(startDate, occurrencesOnEachDay: [2, 2, 2, 2, 2, 2, 2]) + let startDate = DateComponents(year: 2016, month: 01, day: 01) + let schedule = OCKCareSchedule.weeklySchedule(withStartDate: startDate as DateComponents, occurrencesOnEachDay: [2, 2, 2, 2, 2, 2, 2]) // Get the localized strings to use for the activity. let title = NSLocalizedString("Ibuprofen", comment: "") let summary = NSLocalizedString("200mg", comment: "") let instructions = NSLocalizedString("Take with food.", comment: "") - let activity = OCKCarePlanActivity.interventionWithIdentifier( - activityType.rawValue, + let activity = OCKCarePlanActivity.intervention( + withIdentifier: activityType.rawValue, groupIdentifier: nil, title: title, text: summary, - tintColor: Colors.Green.color, + tintColor: Colors.green.color, instructions: instructions, imageURL: nil, schedule: schedule, diff --git a/Sample/OCKSample/WatchConnectivityManager.swift b/Sample/OCKSample/WatchConnectivityManager.swift new file mode 100644 index 000000000..8475120ff --- /dev/null +++ b/Sample/OCKSample/WatchConnectivityManager.swift @@ -0,0 +1,299 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import WatchConnectivity + +class WatchConnectivityManager : NSObject { + + // MARK: Properties + var store : OCKCarePlanStore + var session : WCSession + + var eventUpdatesFromWatch = [String]() + + + // MARK: Initialization + + init(withStore store : OCKCarePlanStore) { + self.store = store + self.session = WCSession.default() + + super.init() + + session.delegate = self + + if (WCSession.isSupported()) { + session.activate() + } + } +} + +// MARK: Outgoing messages + +extension WatchConnectivityManager : OCKCarePlanStoreDelegate { + + func carePlanStore(_ store: OCKCarePlanStore, didReceiveUpdateOf event: OCKCarePlanEvent) { + + if event.activity.type != .intervention { + return + } + + let calendar = Calendar(identifier: Calendar.Identifier.gregorian) + + let today = calendar.dateComponents([.day, .month, .year, .era], from: Date()) + let eventIsToday = (today.day == event.date.day && today.month == event.date.month && today.year == event.date.year && today.era == event.date.era) + + let eventUpdateString = hashEventUpdate(event.activity.identifier, eventIndex: event.occurrenceIndexOfDay, state: event.state) + if let hashIndex = eventUpdatesFromWatch.index(of: eventUpdateString) { + eventUpdatesFromWatch.remove(at: hashIndex) + return + } + + if eventIsToday { + self.store.events(onDate: today, type: .intervention, completion: { (allEventsArray, errorOrNil) in + let eventsCompleted = allEventsArray.map({$0.filter({$0.state == OCKCarePlanEventState.completed}).count}).reduce(0, +) + let totalEvents = allEventsArray.map({$0.count}).reduce(0, +) + let completionPercentage = round(Float(eventsCompleted) * 100.0 / Float(totalEvents)) + + if self.session.isReachable { + let data = NSMutableData() + let encoder = NSKeyedArchiver(forWritingWith: data) + + encoder.encode("updateEvent", forKey: "type") + encoder.encode(self.parseEventToDictionary(event), forKey: "event") + encoder.encode(Int64(completionPercentage), forKey: "currentCompletionPercentage") + + encoder.finishEncoding() + self.session.sendMessageData(data as Data, replyHandler: nil, errorHandler: nil) + } else { + try? self.session.updateApplicationContext(["currentCompletionPercentage" : completionPercentage, "eventsRemaining" : totalEvents - eventsCompleted]) + } + }) + } + } + + func carePlanStoreActivityListDidChange(_ store: OCKCarePlanStore) { + if session.isReachable == true { + // Only update watch if the watch app is reachable ("paired and active Apple Watch is in range and the associated Watch app is running in the foreground") + parseEntireStore({_ in }) + } else { + // If not reachable, send background user info to update complications + let calendar = Calendar(identifier: Calendar.Identifier.gregorian) + let today = calendar.dateComponents([.day, .month, .year, .era], from: Date()) + + self.store.events(onDate: today, type: .intervention, completion: { (allEventsArray, errorOrNil) in + let eventsCompleted = allEventsArray.map({$0.filter({$0.state == OCKCarePlanEventState.completed}).count}).reduce(0, +) + let totalEvents = allEventsArray.map({$0.count}).reduce(0, +) + let completionPercentage = round(Float(eventsCompleted) * 100.0 / Float(totalEvents)) + + try? self.session.updateApplicationContext(["currentCompletionPercentage" : completionPercentage, "eventsRemaining" : totalEvents - eventsCompleted]) + }) + } + } +} + +// MARK: Incoming messages + +extension WatchConnectivityManager : WCSessionDelegate { + + func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { + if activationState == .activated { + store.watchDelegate = self + } else { + store.watchDelegate = nil + } + } + + func sessionDidBecomeInactive(_ session: WCSession) { + + } + + func sessionDidDeactivate(_ session: WCSession) { + WCSession.default().activate() + } + + func session(_ session: WCSession, didReceiveMessageData messageData: Data, replyHandler: @escaping (Data) -> Void) { + let decoder = NSKeyedUnarchiver(forReadingWith: messageData) + defer { + decoder.finishDecoding() + } + + let type = decoder.decodeObject(forKey: "type") as! String + + switch type { + case "getAllData": + parseEntireStore({ (storeDictionary) in + replyHandler(storeDictionary) + }) + + case "updateEventState": + let activityIdentifier = decoder.decodeObject(forKey: "activityIdentifier") as! String + let eventIndex = UInt(decoder.decodeInt64(forKey: "eventIndex")) + let completed = decoder.decodeBool(forKey: "completedState") + + var updatedEvent : OCKCarePlanEvent? + + let calendar = Calendar(identifier: Calendar.Identifier.gregorian) + + let today = calendar.dateComponents([.day, .month, .year, .era], from: Date()) + + store.events(onDate: today, type: .intervention, completion: { (allEventsArray, errorOrNil) in + for activityGroup in allEventsArray { + if !activityGroup.isEmpty && activityGroup[0].activity.identifier == activityIdentifier { + for event in activityGroup { + if event.occurrenceIndexOfDay == eventIndex { + updatedEvent = event + break + } + } + } + } + + guard let newEvent = updatedEvent else { + self.parseEntireStore({ _ in }) + return + } + + self.store.update(newEvent, + with: nil, + state: completed ? .completed : .notCompleted, + completion: { (success, event, errorOrNil) in + let replyData = NSMutableData() + let encoder = NSKeyedArchiver(forWritingWith: replyData) + encoder.encode("updateEventResponse", forKey: "type") + encoder.encode(success, forKey: "success") + + encoder.finishEncoding() + replyHandler(replyData as Data) + if success { + self.eventUpdatesFromWatch.append(self.hashEventUpdate(activityIdentifier, eventIndex: eventIndex, state: completed ? .completed : .notCompleted)) + } + }) + }) + + default: + replyHandler(Data()) + } + } + + + // MARK: Data parsing + + func parseEntireStore(_ initialCompletion: @escaping (Data) -> Void) { + let data = NSMutableData() + let encoder = NSKeyedArchiver(forWritingWith: data) + encoder.encode("allData", forKey: "type") + + var activitiesArray = [[String : Any]]() + var masterEventsArray = [String : [[String : Any]]]() + + let calendar = Calendar(identifier: Calendar.Identifier.gregorian) + + let today = calendar.dateComponents([.day, .month, .year, .era], from: Date()) + + + self.store.events(onDate: today, type: .intervention, completion: { (allEventsArray, errorOrNil) in + // allEventsArray is grouped by activity. + var order = [String]() + var activitiesParsed = 0 + for eventActivityGroup in allEventsArray { + if eventActivityGroup.count == 0 { + continue + } + + var activityEventArray = [[String : Any]]() + activitiesArray.append(self.parseActivityToDictionary(eventActivityGroup[0].activity, numberOfEventsForToday: UInt(eventActivityGroup.count))) + for event in eventActivityGroup { + activityEventArray.append(self.parseEventToDictionary(event)) + } + masterEventsArray[eventActivityGroup[0].activity.identifier] = activityEventArray + order.append(eventActivityGroup[0].activity.identifier) + + activitiesParsed += 1 + if activitiesParsed == 2 { + let initialReplyData = NSMutableData() + let initialEncoder = NSKeyedArchiver(forWritingWith: initialReplyData) + initialEncoder.encode("allDataInitial", forKey: "type") + initialEncoder.encode(order, forKey: "activityOrder") + initialEncoder.encode(activitiesArray, forKey: "activities") + initialEncoder.encode(masterEventsArray, forKey: "events") + + initialEncoder.finishEncoding() + initialCompletion(initialReplyData as Data) + } + } + + encoder.encode(order, forKey: "activityOrder") + encoder.encode(activitiesArray, forKey: "activities") + encoder.encode(masterEventsArray, forKey: "events") + + encoder.finishEncoding() + self.session.sendMessageData(data as Data, replyHandler: nil, errorHandler: nil) + }) + + } + + func parseActivityToDictionary(_ activity: OCKCarePlanActivity, numberOfEventsForToday: UInt) -> [String : Any] { + var activityDictionary = [String: Any]() + activityDictionary["identifier"] = activity.identifier + activityDictionary["title"] = activity.title + + if activity.text != nil { + activityDictionary["text"] = activity.text + } + + if activity.tintColor != nil { + let colorsArray = activity.tintColor?.cgColor.components + if colorsArray != nil { + activityDictionary["tintColor"] = [colorsArray![0], colorsArray![1], colorsArray![2], colorsArray![3]] + } + } + + activityDictionary["numberOfEventsForToday"] = numberOfEventsForToday + + return activityDictionary + } + + func parseEventToDictionary(_ event: OCKCarePlanEvent) -> [String : Any] { + var eventDictionary = [String: Any]() + eventDictionary["occurenceIndexOfDay"] = event.occurrenceIndexOfDay + eventDictionary["activityIdentifier"] = event.activity.identifier + eventDictionary["state"] = event.state.rawValue + return eventDictionary + } + + // MARK: Handling concurency with watch + + func hashEventUpdate(_ activityIdentifier : String, eventIndex : UInt, state : OCKCarePlanEventState) -> String { + return "\(activityIdentifier);\(eventIndex);\(state.rawValue)" + } + +} diff --git a/Sample/OCKSample/Weight.swift b/Sample/OCKSample/Weight.swift index c1d69ef02..e47a05df5 100644 --- a/Sample/OCKSample/Weight.swift +++ b/Sample/OCKSample/Weight.swift @@ -37,31 +37,31 @@ import CareKit struct Weight: Assessment, HealthSampleBuilder { // MARK: Activity properties - let activityType: ActivityType = .Weight + let activityType: ActivityType = .weight // MARK: HealthSampleBuilder Properties - let quantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMass)! + let quantityType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)! - let unit = HKUnit.poundUnit() + let unit = HKUnit.pound() // MARK: Activity func carePlanActivity() -> OCKCarePlanActivity { // Create a weekly schedule. - let startDate = NSDateComponents(year: 2016, month: 01, day: 01) - let schedule = OCKCareSchedule.weeklyScheduleWithStartDate(startDate, occurrencesOnEachDay: [1, 1, 1, 1, 1, 1, 1]) + let startDate = DateComponents(year: 2016, month: 01, day: 01) + let schedule = OCKCareSchedule.weeklySchedule(withStartDate: startDate as DateComponents, occurrencesOnEachDay: [1, 1, 1, 1, 1, 1, 1]) // Get the localized strings to use for the assessment. let title = NSLocalizedString("Weight", comment: "") let summary = NSLocalizedString("Early morning", comment: "") - let activity = OCKCarePlanActivity.assessmentWithIdentifier( - activityType.rawValue, + let activity = OCKCarePlanActivity.assessment( + withIdentifier: activityType.rawValue, groupIdentifier: nil, title: title, text: summary, - tintColor: Colors.Yellow.color, + tintColor: Colors.yellow.color, resultResettable: false, schedule: schedule, userInfo: nil @@ -74,12 +74,12 @@ struct Weight: Assessment, HealthSampleBuilder { func task() -> ORKTask { // Get the localized strings to use for the task. - let answerFormat = ORKHealthKitQuantityTypeAnswerFormat(quantityType: quantityType, unit: unit, style: .Decimal) + let answerFormat = ORKHealthKitQuantityTypeAnswerFormat(quantityType: quantityType, unit: unit, style: .decimal) // Create a question. let title = NSLocalizedString("Input your weight", comment: "") let questionStep = ORKQuestionStep(identifier: activityType.rawValue, title: title, answer: answerFormat) - questionStep.optional = false + questionStep.isOptional = false // Create an ordered task with a single question. let task = ORKOrderedTask(identifier: activityType.rawValue, steps: [questionStep]) @@ -90,32 +90,32 @@ struct Weight: Assessment, HealthSampleBuilder { // MARK: HealthSampleBuilder /// Builds a `HKQuantitySample` from the information in the supplied `ORKTaskResult`. - func buildSampleWithTaskResult(result: ORKTaskResult) -> HKQuantitySample { + func buildSampleWithTaskResult(_ result: ORKTaskResult) -> HKQuantitySample { // Get the first result for the first step of the task result. - guard let firstResult = result.firstResult as? ORKStepResult, stepResult = firstResult.results?.first else { fatalError("Unexepected task results") } + guard let firstResult = result.firstResult as? ORKStepResult, let stepResult = firstResult.results?.first else { fatalError("Unexepected task results") } // Get the numeric answer for the result. - guard let weightResult = stepResult as? ORKNumericQuestionResult, weightAnswer = weightResult.numericAnswer else { fatalError("Unable to determine result answer") } + guard let weightResult = stepResult as? ORKNumericQuestionResult, let weightAnswer = weightResult.numericAnswer else { fatalError("Unable to determine result answer") } // Create a `HKQuantitySample` for the answer. let quantity = HKQuantity(unit: unit, doubleValue: weightAnswer.doubleValue) - let now = NSDate() + let now = Date() - return HKQuantitySample(type: quantityType, quantity: quantity, startDate: now, endDate: now) + return HKQuantitySample(type: quantityType, quantity: quantity, start: now, end: now) } /** Uses an NSMassFormatter to determine the string to use to represent the supplied `HKQuantitySample`. */ - func localizedUnitForSample(sample: HKQuantitySample) -> String { - let formatter = NSMassFormatter() - formatter.forPersonMassUse = true - formatter.unitStyle = .Short + func localizedUnitForSample(_ sample: HKQuantitySample) -> String { + let formatter = MassFormatter() + formatter.isForPersonMassUse = true + formatter.unitStyle = .short - let value = sample.quantity.doubleValueForUnit(unit) - let formatterUnit = NSMassFormatterUnit.Pound + let value = sample.quantity.doubleValue(for: unit) + let formatterUnit = MassFormatter.Unit.pound - return formatter.unitStringFromValue(value, unit: formatterUnit) + return formatter.unitString(fromValue: value, unit: formatterUnit) } } diff --git a/Sample/OCKSampleWatch Extension/ActivityRow.swift b/Sample/OCKSampleWatch Extension/ActivityRow.swift new file mode 100644 index 000000000..3f88e149c --- /dev/null +++ b/Sample/OCKSampleWatch Extension/ActivityRow.swift @@ -0,0 +1,49 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import WatchKit + +class ActivityRow : NSObject { + + // MARK: Properties + + var activity : WCKActivity? + + @IBOutlet var titleLabel: WKInterfaceLabel! + @IBOutlet var textLabel: WKInterfaceLabel! + + // MARK: Rendering + + func load(fromActivity activity: WCKActivity) { + self.activity = activity + self.titleLabel.setText(activity.title) + self.textLabel.setText(activity.text) + } +} diff --git a/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json b/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json new file mode 100644 index 000000000..bb7ff9728 --- /dev/null +++ b/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json @@ -0,0 +1,27 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "filename" : "circular-stack-38mm@2x.png", + "screen-width" : "<=145", + "scale" : "2x" + }, + { + "idiom" : "watch", + "filename" : "circular-stack-42mm@2x.png", + "screen-width" : ">145", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/circular-stack-38mm@2x.png b/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/circular-stack-38mm@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a16044de154a9f73397ac2ae65799684e6f29ae8 GIT binary patch literal 286 zcmV+(0pb3MP)3~|2REl|Lcq-%DBeIJqtcE-a{+FSPQ3s}H#u+wv#BE&U@6jsFPVkDvPoA3d zV#nJD&W|wOBkvQpBp3$_T0(~ygqG>QAql8D6jT9=4h4&VNr!?-z!c>_ndLjUz&ZBuffrn-v3RO7N4UfRcJYQ=+@!JiOv)@z@PK2h zSGU@))|@}$Bq_5z$K9IHrmG#$*%EwY6OgHfW`sC8lYi7uLh_W(8p*C zWQ2Z5V=+S;lYbx+w9{D30;I8cMUL4YkQwsot}vgbu^3d%rW+vBs>xtJNR|_2mLK|g zx4kvUJ5JMBJTDHza;ge65mz7)&1Ga|qlIP(&iwxRF7DG145", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/mod-small-stack-38mm@2x.png b/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/mod-small-stack-38mm@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..93ec1a6227b3b8bc7aa4201e2aa08bc0e53f2c46 GIT binary patch literal 543 zcmV+)0^t3LP)Vkbl;R$B-`Aw?j? zHbO`jQ4l+AVj~7uLkL#JV&~4dIg-01-o9p+*?HglGYmW5G*nb1>2X{^6Q^+y>-dNq z&*MD%T=fO-iQr9e3Iq6s510+!ubVxMN`Y&5ghQPIf_~!(ZpV4H9()6Mh#QEu@vh-k zoM%tB02E1j4|ldPSM?4T!uveV_TarA=h@vhK#`;u@v4UcExirTbGz_fiu3Gsqe#*N z_=KTd6xoZu;ADjH8p4Il@kqJb>rykqNR0p^k$RTDrJ)FeH3AGq*r*X;Bf@fx0Lu}U zY6Mt{FjphMT!b0rA<=KGVJ3?6Y!y>A08GVsw%R&6A7G`A;VU7tJiFsOD=^VVfQgX# zw|R*3>?NlA5I!BU`~whl9Si?4d?94C)u_%WlJqd%;LJXUzsLDF&wg$m+|s{=38Prt z$M8jrR>M021c(A-_U9)xhq2bC>k1%1tSg(9$vuQmqS@-6J88=v=%gY^n|OhvT?T*0 zZ2ai8)*n?Pf9RL%4__MhSwFpq7D95QGUr%%)YXqViHv3u)u7b+isw3eh5|7|W$?Y%{cw zf3=bSbLaZM(8e^0^Jch z%BDa^g!Zy2&>ms6YznMK%Kvm>E>c~{%GPv*$+9Uh8L2Mo%OyfAVfSG-On6bXILt)Pf zc~Uus_c*af5MOa2&eCtSjl~fW0us#c0mM9#B1Bz~0P_VsnB7H)S@eY58&nr0z$~B- zQ@a2$g}#upt~Lb;FpH|wG_nJT5!LC~@;|lVW!+49Qn`-DINYG+2kymL`l^xOhCu>M z7oOqbHlc5EJI>OEU-&Jjrl^oOQ9aQu)d^V&eMvJAG&v%*%9Bb59#}tSj^bgQr7f-G Ze*qxWjFxXsO7H*x002ovPDHLkV1nMA1@8a= literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json b/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json new file mode 100644 index 000000000..91b6449a6 --- /dev/null +++ b/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json @@ -0,0 +1,27 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "filename" : "utilitarian-38mm@2x.png", + "screen-width" : "<=145", + "scale" : "2x" + }, + { + "idiom" : "watch", + "filename" : "utilitarian-42mm@2x.png", + "screen-width" : ">145", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/utilitarian-38mm@2x.png b/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/utilitarian-38mm@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b9ca4e726e70323756865f43f8fa6a1ef4aa12b9 GIT binary patch literal 366 zcmV-!0g?WRP)z7{~F?j)y@6nS59To55%_EJllUQ4XwPIqonBfJa2Ph+8XR%aITihX%MA1U=F1aio|Zzt-C4jk7BPV4js72(&i6fo1Ea3)}^LE%`yb%Vm|fL?>bUcgaGZ+Dh) zqCQ!;n?S2Er?ba}+PG4J^XOK}UCh^H|Lt(3(-zjSUyi=wxV(%ix3IoWcLvT8kpKVy M07*qoM6N<$g7++>CjbBd literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/utilitarian-42mm@2x.png b/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/utilitarian-42mm@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..66e01363cd35927e1571800bb21c14ea6d470937 GIT binary patch literal 393 zcmV;40e1e0P)v`90ra*q!MpRNY?0N6h0n&hQK0@HysmT5{u9#S*44 zh9msIrKAY*@o(tYIm zm!2*QDX~^#JKs>AmEN zIOcSYWo+C-x`E}=dr7Autm^g_u!*M)k^fkUIeovb*eEXYm-vdeL!~{uk2(Em>K)$W nE0o4rgRAIYc~&udlN2rhF4I)81zAwk00000NkvXXu0mjfsfo5) literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/X-Large.imageset/Contents.json b/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/X-Large.imageset/Contents.json new file mode 100644 index 000000000..39576cce9 --- /dev/null +++ b/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/X-Large.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "watch", + "filename" : "xl-stack-38mm@2x.png", + "screen-width" : "<=145", + "scale" : "2x" + }, + { + "idiom" : "watch", + "filename" : "xl-stack-42mm@2x.png", + "screen-width" : ">145", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/X-Large.imageset/xl-stack-38mm@2x.png b/Sample/OCKSampleWatch Extension/Assets.xcassets/Complication.complicationset/X-Large.imageset/xl-stack-38mm@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2f912fb9a1e7163531d982972c45932be30b3ee9 GIT binary patch literal 1699 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 Void) { + handler(CLKComplicationTimeTravelDirections()) + } + + func getPrivacyBehavior(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) { + handler(.hideOnLockScreen) + } + + // MARK: - Timeline Population + + func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping((CLKComplicationTimelineEntry?) -> Void)) { + // Call the handler with the current timeline entry + let template = getTemplate(forCompletionPercentage: getCurrentCompletionPercentage(), complication: complication) + if template != nil { + handler(CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template!)) + } else { + handler(nil) + } + } + + func getTimelineEntries(for complication: CLKComplication, before date: Date, limit: Int, withHandler handler: @escaping (([CLKComplicationTimelineEntry]?) -> Void)) { + // Call the handler with the timeline entries prior to the given date + handler(nil) + } + + func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: @escaping (([CLKComplicationTimelineEntry]?) -> Void)) { + // Call the handler with the timeline entries after to the given date + handler(nil) + } + + // MARK: - Placeholder Templates + + func getPlaceholderTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) { + // This method will be called once per supported complication, and the results will be cached + handler(getTemplate(forCompletionPercentage: nil, complication: complication)) + } + + + // MARK: Rendering Templates + + func getTemplate(forCompletionPercentage completionPercentage : Int?, complication : CLKComplication) -> CLKComplicationTemplate? { + var textToDisplay : String + if completionPercentage == nil || completionPercentage == -1 { + // completionPercentage of -1 indicates request for nil to be displayed by InterfaceController + textToDisplay = "--%" + } else { + textToDisplay = "\(completionPercentage!)%" + } + + + switch complication.family { + case .modularLarge: + let template = CLKComplicationTemplateModularLargeStandardBody() + template.headerTextProvider = CLKSimpleTextProvider(text: "Care Completion") + template.tintColor = InterfaceController.watchTintColor + template.body1TextProvider = CLKSimpleTextProvider(text: textToDisplay) + + if completionPercentage != nil && completionPercentage != -1 { + let eventsRemaining = getEventsRemaining() + switch eventsRemaining { + case 0: + template.body2TextProvider = CLKSimpleTextProvider(text: "Care Plan complete") + case 1: + template.body2TextProvider = CLKSimpleTextProvider(text: "1 event remaining") + default: + template.body2TextProvider = CLKSimpleTextProvider(text: "\(getEventsRemaining()) events remaining") + } + } + + return template + + case .modularSmall: + let template = CLKComplicationTemplateModularSmallStackImage() + template.line1ImageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Complication/Modular")!) + template.line2TextProvider = CLKSimpleTextProvider(text: textToDisplay) + template.tintColor = InterfaceController.watchTintColor + return template + + case .utilitarianSmall: + let template = CLKComplicationTemplateUtilitarianSmallFlat() + template.imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Complication/Utilitarian")!) + template.textProvider = CLKSimpleTextProvider(text: textToDisplay) + template.tintColor = InterfaceController.watchTintColor + return template + + case .utilitarianLarge: + let template = CLKComplicationTemplateUtilitarianLargeFlat() + if completionPercentage == nil && completionPercentage != -1 { + template.textProvider = CLKSimpleTextProvider(text: "Care Plan") + } else { + switch completionPercentage! { + case 100: + template.textProvider = CLKSimpleTextProvider(text: "Care Complete") + default: + template.textProvider = CLKSimpleTextProvider(text: "Care Plan: " + textToDisplay) + } + } + template.imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Complication/Utilitarian")!) + template.tintColor = InterfaceController.watchTintColor + return template + + case .circularSmall: + let template = CLKComplicationTemplateCircularSmallStackImage() + template.line1ImageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Complication/Circular")!) + template.line2TextProvider = CLKSimpleTextProvider(text: textToDisplay) + template.tintColor = InterfaceController.watchTintColor + return template + + case .extraLarge: + let template = CLKComplicationTemplateExtraLargeStackImage() + template.line1ImageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Complication/X-Large")!) + template.line2TextProvider = CLKSimpleTextProvider(text: textToDisplay) + template.tintColor = InterfaceController.watchTintColor + template.highlightLine2 = false + return template + + default: + return nil + } + } + + // MARK: Updates + + func getCurrentCompletionPercentage() -> Int { + let defaults = UserDefaults.standard + return defaults.integer(forKey: "currentCompletionPercentage") + } + + func getEventsRemaining() -> Int { + let defaults = UserDefaults.standard + return defaults.integer(forKey: "eventsRemaining") + } + +} diff --git a/Sample/OCKSampleWatch Extension/EventRow.swift b/Sample/OCKSampleWatch Extension/EventRow.swift new file mode 100644 index 000000000..b0aba7d24 --- /dev/null +++ b/Sample/OCKSampleWatch Extension/EventRow.swift @@ -0,0 +1,101 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import WatchKit + +class EventRow : NSObject { + + // MARK: Properties + + var activityIdentifier : String? + var tintColor : UIColor? + var rowIndex : Int? + var buttons : [WKInterfaceButton] = [] + var displayCompleted = [false, false, false] + var parentInterfaceController : InterfaceController? + + @IBOutlet var leftButton: WKInterfaceButton! + @IBOutlet var centerButton: WKInterfaceButton! + @IBOutlet var rightButton: WKInterfaceButton! + + + // MARK: Rendering + + func load(fromActivity activity: WCKActivity, withRowIndex rowIndex: Int, parent: InterfaceController) { + self.activityIdentifier = activity.identifier + self.tintColor = activity.tintColor + self.rowIndex = rowIndex + self.buttons = [leftButton, centerButton, rightButton] + self.parentInterfaceController = parent + + for columnIndex in 0..<3 { + if 3 * rowIndex + columnIndex < activity.eventsForToday.count { + buttons[columnIndex].setHidden(false) + buttons[columnIndex].setBackgroundColor(tintColor) + + displayCompleted[columnIndex] = (activity.eventsForToday[3 * rowIndex + columnIndex]!.state == .completed) + + buttons[columnIndex].setBackgroundImageNamed(displayCompleted[columnIndex] ? "bubble-fill" : "bubble-empty") + } else { + buttons[columnIndex].setHidden(true) + } + } + } + + func updateButton(withColumnIndex columnIndex: Int, toState state : WCKEventState) { + let completed = (state == .completed) + buttons[columnIndex].setBackgroundImageNamed(completed ? "bubble-fill" : "bubble-empty") + displayCompleted[columnIndex] = completed + } + + func updateButton(withEventIndex eventIndex : Int, toState state : WCKEventState) { + updateButton(withColumnIndex: eventIndex - 3 * rowIndex!, toState: state) + } + + // MARK: Handle user inputs + + func didSelectButton(withColumnIndex columnIndex : Int) { + updateButton(withColumnIndex: columnIndex, toState: displayCompleted[columnIndex] ? .notCompleted : .completed) + parentInterfaceController?.updateDataStoreEvent(withActivityIdentifier: activityIdentifier!, atIndex: 3 * rowIndex! + columnIndex, toCompletedState: displayCompleted[columnIndex]) + } + + @IBAction func leftButtonPressed() { + didSelectButton(withColumnIndex: 0) + } + + @IBAction func centerButtonPressed() { + didSelectButton(withColumnIndex: 1) + } + + @IBAction func rightButtonPressed() { + didSelectButton(withColumnIndex: 2) + } + +} diff --git a/Sample/OCKSampleWatch Extension/ExtensionDelegate.swift b/Sample/OCKSampleWatch Extension/ExtensionDelegate.swift new file mode 100644 index 000000000..e74c0cb31 --- /dev/null +++ b/Sample/OCKSampleWatch Extension/ExtensionDelegate.swift @@ -0,0 +1,47 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import WatchKit + +class ExtensionDelegate: NSObject, WKExtensionDelegate { + + func applicationDidFinishLaunching() { + // Perform any final initialization of your application. + } + + func applicationDidBecomeActive() { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillResignActive() { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, etc. + } +} diff --git a/Sample/OCKSampleWatch Extension/Info.plist b/Sample/OCKSampleWatch Extension/Info.plist new file mode 100644 index 000000000..f02b1daf9 --- /dev/null +++ b/Sample/OCKSampleWatch Extension/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + OCKSampleWatch Extension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + CLKComplicationPrincipalClass + $(PRODUCT_MODULE_NAME).ComplicationController + CLKComplicationSupportedFamilies + + CLKComplicationFamilyModularLarge + CLKComplicationFamilyModularSmall + CLKComplicationFamilyUtilitarianSmall + CLKComplicationFamilyUtilitarianLarge + CLKComplicationFamilyCircularSmall + CLKComplicationFamilyExtraLarge + + NSExtension + + NSExtensionAttributes + + WKAppBundleIdentifier + com.example.apple-samplecode.CareKit.watchkitapp + + NSExtensionPointIdentifier + com.apple.watchkit + + WKExtensionDelegateClassName + $(PRODUCT_MODULE_NAME).ExtensionDelegate + + diff --git a/Sample/OCKSampleWatch Extension/InterfaceController.swift b/Sample/OCKSampleWatch Extension/InterfaceController.swift new file mode 100644 index 000000000..bc779dc46 --- /dev/null +++ b/Sample/OCKSampleWatch Extension/InterfaceController.swift @@ -0,0 +1,446 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import WatchKit +import Foundation +import WatchConnectivity +import ClockKit + + +class InterfaceController: WKInterfaceController { + + // MARK: Properties + + static let watchTintColor = UIColor.init(red: 239.0/255.0, green: 68.0/255.0, blue: 91.0/255.0, alpha: 1.0) + + @IBOutlet var loaderGroup: WKInterfaceGroup! + @IBOutlet var loaderImage: WKInterfaceImage! + @IBOutlet var loaderLabel: WKInterfaceLabel! + + @IBOutlet var tableView: WKInterfaceTable! + + let session = WCSession.default() + var activities = [String : WCKActivity]() + var activityOrder = [String]() + var activityRowIndices = [String : Int]() + + // MARK: Initialization + + override func awake(withContext context: Any?) { + super.awake(withContext: context) + session.delegate = self + session.activate() + } + + override func willActivate() { + self.setTitle("") + + if session.activationState != .activated { + session.activate() + } else { + loadData() + } + } + + func loadData() { + self.setTitle("") + loaderGroup.setHidden(false) + loaderImage.startAnimating() + loaderLabel.setText("Loading\nCare Card") + activities.removeAll() + activityOrder.removeAll() + activityRowIndices.removeAll() + tableView.setHidden(false) + tableView.removeRows(at: IndexSet.init(integersIn: 0.. Int { + let eventsComplete = self.activities.values.map({$0.getNumberOfCompletedEvents()}).reduce(0, +) + let eventsTotal = self.activities.values.map({$0.eventsForToday.count}).reduce(0, +) + + if eventsTotal == 0 { + return 0 + } + + return Int(round(Float(eventsComplete) * 100.0 / Float(eventsTotal))) + } + + + // MARK: Table Navigation + + func getRowIndex(ofEventIndex eventIndex : Int) -> Int { + return Int(floor(Float(eventIndex) / 3.0)) + } + + + // MARK: Sending Updates + + func updateDataStoreEvent(withActivityIdentifier activityIdentifier : String, atIndex eventIndex : Int, toCompletedState completedState : Bool) { + + if !session.isReachable { + didLosePhoneConnection() + return + } + + let data = NSMutableData() + let encoder = NSKeyedArchiver(forWritingWith: data) + encoder.encode("updateEventState", forKey: "type") + encoder.encode(activityIdentifier, forKey: "activityIdentifier") + encoder.encode(Int64(eventIndex), forKey: "eventIndex") + encoder.encode(completedState, forKey: "completedState") + + self.activities[activityIdentifier]?.eventsForToday[eventIndex]!.state = completedState ? .completed : .notCompleted + updateTitleLabel(withCompletionPercentage: nil) + updateComplications(withCompletionPercentage: nil) + + encoder.finishEncoding() + session.sendMessageData(data as Data, replyHandler: {data in + let decoder = NSKeyedUnarchiver(forReadingWith: data) + if decoder.decodeBool(forKey: "success") { + } else { + self.activities[activityIdentifier]?.eventsForToday[eventIndex]!.state = completedState ? .notCompleted : .completed + self.updateEventButton(forActivityIdentifier: activityIdentifier, eventIndex: eventIndex) + self.updateTitleLabel(withCompletionPercentage: nil) + self.updateComplications(withCompletionPercentage: nil) + self.alertUserForFailedEventUpdate() + } + }, errorHandler: {(error) in + self.alertUserForFailedEventUpdate() + self.messagingErrorHandler(error as NSError)}) + } + + func messagingErrorHandler(_ error : Error) { + NSLog("error: \(error)\nsession reachable = \(session.isReachable)") + if session.activationState != .activated { + didLosePhoneConnection() + } else { + loadData() + } + } + + func alertUserForFailedEventUpdate() { + presentAlert(withTitle: "Lost Connection", message: "Event could not be updated", preferredStyle: .alert, actions: [WKAlertAction(title: "Dismiss", style: .default, handler: {})]) + } + + + // MARK: Fetching Data + + func getAllData() { + if session.activationState == .activated { + let data = NSMutableData() + let encoder = NSKeyedArchiver(forWritingWith: data) + encoder.encode("getAllData", forKey: "type") + encoder.finishEncoding() + session.sendMessageData(data as Data, replyHandler: {(data) in + let decoder = NSKeyedUnarchiver(forReadingWith: data) + defer { + decoder.finishDecoding() + } + + let type = decoder.decodeObject(forKey: "type") as! String + guard type == "allDataInitial" else { + NSLog("Bad message recieved") + return + } + + if self.activities.isEmpty { + self.loadAllData(fromData: decoder, isFullData: false) + } + + }, errorHandler: messagingErrorHandler) + } else { + didLosePhoneConnection() + } + } + +} + + + // MARK: Handling Updates + +extension InterfaceController: WCSessionDelegate { + + func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { + if activationState == .activated { + loadData() + } else { + didLosePhoneConnection() + } + } + + func session(_ session: WCSession, didReceiveMessageData messageData: Data) { + let decoder = NSKeyedUnarchiver(forReadingWith: messageData) + defer { + decoder.finishDecoding() + } + + let type = decoder.decodeObject(forKey: "type") as! String + + switch type { + case "updateEvent": + updateEventHandler(fromDictionary: decoder.decodeObject(forKey: "event") as! [String : AnyObject], + completionPercentage: Int(decoder.decodeInt64(forKey: "currentCompletionPercentage"))) + + case "allData": + self.loadAllData(fromData: decoder, isFullData: true) + self.loaderImage.stopAnimating() + self.loaderGroup.setHidden(true) + self.updateTitleLabel(withCompletionPercentage: nil) + self.updateComplications(withCompletionPercentage: nil) + + default: + NSLog("Invalid message data type recieved") + } + } + + func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) { + guard let completionPercentage = applicationContext["currentCompletionPercentage"] as? Int else { + return + } + + guard let eventsRemaining = applicationContext["eventsRemaining"] as? Int else { + return + } + + let defaults = UserDefaults.standard + defaults.set(completionPercentage, forKey: "currentCompletionPercentage") + defaults.set(eventsRemaining, forKey: "eventsRemaining") + + let server = CLKComplicationServer.sharedInstance() + for complication in server.activeComplications! { + server.reloadTimeline(for: complication) + } + } + + func updateEventHandler(fromDictionary eventDictionary : [String : AnyObject], completionPercentage : Int) { + let didUpdateEvent = loadEvent(fromDictionary: eventDictionary, updateDisplay: true) + if didUpdateEvent { + updateTitleLabel(withCompletionPercentage: completionPercentage) + updateComplications(withCompletionPercentage: completionPercentage) + } + } + + // MARK: Loading Data + + func loadAllData(fromData decoder: NSKeyedUnarchiver, isFullData : Bool) { + var newActivities = [String]() + if isFullData || activityOrder.isEmpty { + activityOrder = decoder.decodeObject(forKey: "activityOrder") as! [String] + } + + let activitiesArray = decoder.decodeObject(forKey: "activities") as! [[String : AnyObject]] + for activityDictionary in activitiesArray { + if self.loadActivity(fromDictionary: activityDictionary) { + newActivities.append(activityDictionary["identifier"] as! String) + } + } + + let masterEventsArray = decoder.decodeObject(forKey: "events") as! [String : [[String : AnyObject]]] + for (activityIdentifier, eventActivityGroup) in masterEventsArray { + if newActivities.contains(activityIdentifier) { + for eventDictionary in eventActivityGroup { + _ = self.loadEvent(fromDictionary: eventDictionary, updateDisplay: false) + } + } + } + + for newIdentifier in newActivities { + appendActivityToTable(self.activities[newIdentifier]!) + } + } + + func loadActivity(fromDictionary activityDictionary: [String : AnyObject]) -> Bool { + var tintColor : UIColor? + if activityDictionary["tintColor"] != nil { + let colorComponents = activityDictionary["tintColor"] as! [CGFloat] + tintColor = UIColor.init(red: colorComponents[0], + green: colorComponents[1], + blue: colorComponents[2], + alpha: colorComponents[3]) + } + + let newActivity = WCKActivity.init(interventionWithIdentifier: activityDictionary["identifier"] as! String, + title: activityDictionary["title"] as! String, + text: activityDictionary["text"] as? String, + tintColor: tintColor, + numberOfEventsForToday: activityDictionary["numberOfEventsForToday"] as! UInt) + + let new = !self.activities.keys.contains(newActivity!.identifier) + if new { + self.activities[newActivity!.identifier] = newActivity! + } + return new + } + + func loadEvent(fromDictionary eventDictionary: [String : AnyObject], updateDisplay : Bool) -> Bool { + // Must be called after activity loaded. + let occurenceIndexOfDay = Int(eventDictionary["occurenceIndexOfDay"] as! UInt) + let activityIdentifier = eventDictionary["activityIdentifier"] as! String + var didChange = false + + if occurenceIndexOfDay >= 14 { + NSLog("Only 14 events displayed for a given activity") + return false + } + + if self.activities[activityIdentifier]?.eventsForToday[Int(occurenceIndexOfDay)] != nil { + let newState = WCKEventState(rawValue: eventDictionary["state"] as! Int)! + if self.activities[activityIdentifier]?.eventsForToday[Int(occurenceIndexOfDay)]!.state != newState { + self.activities[activityIdentifier]?.eventsForToday[Int(occurenceIndexOfDay)]!.state = WCKEventState(rawValue: eventDictionary["state"] as! Int)! + didChange = true + } + } else { + let newEvent = WCKEvent(occurenceIndexOfDay: occurenceIndexOfDay, + activityIdentifier: activityIdentifier, + state: WCKEventState(rawValue: eventDictionary["state"] as! Int)!) + self.activities[activityIdentifier]?.eventsForToday[Int(occurenceIndexOfDay)] = newEvent + didChange = true + } + + if updateDisplay && didChange { + updateEventButton(forActivityIdentifier: activityIdentifier, eventIndex: Int(occurenceIndexOfDay)) + } + + return didChange + } +} diff --git a/Sample/OCKSampleWatch Extension/WCKActivity.swift b/Sample/OCKSampleWatch Extension/WCKActivity.swift new file mode 100644 index 000000000..20132d719 --- /dev/null +++ b/Sample/OCKSampleWatch Extension/WCKActivity.swift @@ -0,0 +1,82 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import WatchKit + +enum WCKActivityType { + // Something related to treatment. + case intervention + // Some task in the app. + case assessment +} + +class WCKActivity : NSObject { + + // MARK: Properties + + // Unique identifier string. + let identifier : String + // Group identifier string. + //let groupIdentifier : String? + // The type of activity. + let type : WCKActivityType + // The title of the intervention activity. + var title : String + // A descriptive text for the intervention activity. + var text : String? + // The tint color for the intervention activity. + let tintColor : UIColor? + + // An array of all the events associated with the activity for today. + var eventsForToday : [WCKEvent?] + + + // MARK: Initialization + + init?(interventionWithIdentifier identifier: String, + title: String, + text: String?, + tintColor: UIColor?, + numberOfEventsForToday: UInt) { + self.identifier = identifier + self.type = WCKActivityType.intervention + self.title = title + self.text = text + self.tintColor = tintColor + self.eventsForToday = [WCKEvent?](repeating: nil, count: Int(numberOfEventsForToday)) + } + + // MARK: Event Querying + + func getNumberOfCompletedEvents() -> Int { + return eventsForToday.map({$0?.state == .completed ? 1 : 0}).reduce(0, +) + } + +} diff --git a/Sample/OCKSampleWatch Extension/WCKEvent.swift b/Sample/OCKSampleWatch Extension/WCKEvent.swift new file mode 100644 index 000000000..5b0dbd99d --- /dev/null +++ b/Sample/OCKSampleWatch Extension/WCKEvent.swift @@ -0,0 +1,63 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + + +enum WCKEventState : Int { + // Initial state with no response. + case initial + // Marked as not complete. + case notCompleted + // Marked as complete. + case completed +} + +class WCKEvent : NSObject { + + // MARK: Properties + + // The index of this event on the given day. + let occurenceIndexOfDay : Int + // The identifier of the associated activity. + var activityIdentifier : String + // The state of this event (Initial / NotCompleted / Completed). + var state : WCKEventState + + + // MARK: Initialization + + init(occurenceIndexOfDay: Int, activityIdentifier: String, state: WCKEventState) { + self.occurenceIndexOfDay = occurenceIndexOfDay + self.activityIdentifier = activityIdentifier + self.state = state + } + +} diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/Contents.json b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/Contents.json new file mode 100644 index 000000000..da4a164c9 --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-empty.imageset/Contents.json b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-empty.imageset/Contents.json new file mode 100644 index 000000000..70db80bb1 --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-empty.imageset/Contents.json @@ -0,0 +1,27 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "filename" : "bubble-empty@2x.png", + "screen-width" : "<=145", + "scale" : "2x" + }, + { + "idiom" : "watch", + "filename" : "bubble-empty-42mm@2x.png", + "screen-width" : ">145", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-empty.imageset/bubble-empty-42mm@2x.png b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-empty.imageset/bubble-empty-42mm@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6f7353919de2616cc90491eef2cf9c63ffc4e77a GIT binary patch literal 2159 zcmV-#2$1)QP))3*quo)Y%7HjYfR^#9OHaum| zDX4QU7T|20hQm8}&))UFxk=gS**zQZ7*=8hMka0PI2h{F6S+4&f=h4)_Udtc+wlnQ z#;?Q^-BW5k{`~p4883)NEzo-r)$2H?UgryS8|L@2!d^X*hv17?h*@p!eH~BYFQTto zFTSQ5@oN1K=G6b@iSFP?(YL-ECyA%N6{ENlH|art+HE0cW04SXc8mL-!LLPs_D7Td z>g|n_MZbH27`Vn_n|MN(*8krXx+&xtxC2Lz@%jjUj-TMEZdE!4@4_eWam4{D<)8Sp z=u0O}H~Prg_#PhCT*URb3WwqIdM~1S9oN?DysBo2M&tNEf zZ6mH0bHioWI?1{w!q$4-$JK4wn7uxPD@7ZQolHfO5pn^Z5FLKX8~8qsssB4Vi8{K) zsG?18WUrqf+OlAx6--pfg}5L4W#t>hB>QTy3Yl)aBy2lP*qXARXw$-peDFksTr38a zd{uOxn1-yHh#`Gum9X_US^1u#ZP$(W1IH`mB794+KinzAy#SlWYrqt;2^R|6cP8aS zSR&fmG2;>P%6bJUqhi^&G&80u>=d?NqTH7+5pC{>PKEpszN`2oZpC@Hr_;)&G56qH z#hJyBX!E(9d_X5c9wXMQdn9F}!U?gmBQvYP!{V!+KAC%nMMT@FQ9B`raWD2y%68&1 zGfTt<4~e#=-PHavC&{iXwvj6K9-P+6de$6h$%u}-S<<> zX5l?bmy<^uW3t{%$b)fxR<;bk?}l|1W0h!o%3`5Wfo4K3Qha>>D+ZX|l^cZy4Td#Y z_2fd%!xdTCS4>X_M89}RXpnM+(CSTcA+HttA`RAyeU9CoI~AS7bMU$JhE&M6C{K63 zZF=|+Y0G z8vkhsIahhs{^K4RRaJhPU7w-8OW6?eY{dwOf8cLDH>-L)CA4Xvc8d1$gdO8&D?KXmw2-s7!gU!N}c;S$I!Y_GAsu zD=xzKQg@#ZXv)co%jykyzOk~&w-!Fw4~r_wIob8^*tPk!B73o;NdDcF^Rnv)*(Kyk zvFX*|9XPQMMpcayg*FYgs~<{e2swgBvo~GVd%G$}uF0e7QOv3L=dSFgkLkiW<{89n zp-IY{nx#VCs~97Gkik=#a;f5O!X}{^ibB37qV`k1pnY1<7gOug64X|cg4NDbIiM|zI@2Y9l z;%h>K23v7Uep53cUld}dT!mA+W?FSPMI=5+xkY5RDlpdO*Am6!V>NNu@xX3aR}uCV z)0t-U0 z@zJd8c5yhqDed;P7vbrw>?Y+C5HpF3#WCZQr?p8I(oV>&B74fqN!gG%@o?5S4XgrZ zingWQ*URDzQp-$QokUu!6>H2LN!cusZEq%td6vinl&<7Wd$njwz6sbdlMOUoEB1MpDW|cSCsM|)5r@QEW^(Eg!}Yq?)NRS5 z$aV_bPZn*NFx^a6e5UXk=K)3yM(_*a{P;t+DjkDU#FXYDV-JAOii`29J}dHyP1PK81V0p`b;%*yEqZ;b;RW$kpD(;B zD-Ki>cV literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-empty.imageset/bubble-empty@2x.png b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-empty.imageset/bubble-empty@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e061bfbc4975e84943f21a8cc95101a9d3d5b159 GIT binary patch literal 1943 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", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-fill.imageset/bubble-fill-38mm@2x.png b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/bubble-fill.imageset/bubble-fill-38mm@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..16378ecba46c97285b5af3e7262038eea2f40f88 GIT binary patch literal 1230 zcmV;<1Tp)GP)ZEdM6}v0Dz<{{;y?S+II}ymduGnFyYs!8Idh)p`JLaKGw00n z{Qv*9-rMifWM*Rt7GeSBU=})XF{a^P{El9n!U=qfFL4k*HdFAlCXCUJ)mV!)xTc0S z(}Zaqn2Y6QpMQrBu^W5PmzUT|v^DTdT8am-5tlY<5S+zZcvYNbxs&DGUmMorGaSGc zjWtNA|1J2uH17J6j@-!8q!mKwPUl`8&0=|J{DUPuxsZoRS719n!QveH%Y&PRp6x>4 zxEQZV8_-8_OWy@7L#V;V|0yWzyj$K zx@XqguwIkq;#2W3I1yPQ^v|uQQ9ULt6t~!U^$d_8^Tcu7SZjk?O}Y;I#NUU>z%1;= z^|kC=i%Fg0(SOD`M5V|K@zit?=>oi8OGguwPH}wakF?WhCT+u_yc8wMB0M+J z4kMYg5fA1nCtbRX@W5Hkq*-{WA#&2?6;*Cb)l7OG(;FryO*+JJpF<^+R*Fk)DzXu` zm2a$M(z6Yhk~YtjZzwlum6%bS$}AN=3{q~=6V20-G*1qHGu))bDqN3Kl$D14i63s# zmgZ|on#}_*225(lJ;i8AmV1>Z=>|+%qw%X66OBu7CqpK!Elx|)tYgTe)ddPknN@^I zooZWpo{C(J&I~sdEF^UnWnyZ!MRl&tFu!OOiL)RRF+we>Ge0wVRzMoXl^HHCT1Dba z&v0SUDiY_S%qYt#Eu5F(@1j*C&OaIcELuh4{E^}3qE#f$FBwi3ts-$wXCfxLMRmT< zM5KL->U3xLs%RC7b1cK5qE#f$p$t7*zf0Bl0X+lLw|k3Jk}!K1n&aMGppcZ=#gIuK zh-{x0L;NOu88oR6Zx<#fO?D{d(G6ebez_Pe$uj82aFY&-w1O7l!(f78dFahk&DD}D zPY-`nZqh!H*f*6qr0kKXQaIq_&C!x9kCktzWYR|>@pme+LmdDAs1~C9h{(yGO7!C4 zN*`1+=@cGnn4C1(EROpeMoOD_6R$NyPI|m3Qcx>0S^`cNj^-*SJ&xkhk#-o(q`z>N zm`<6D^oZjdaapaFq`)2#Q+Xx_Q7Lgo#6*sI0@Rvb`VH&Ce?*J6d?gkWMyJl$wr8vaiK23B`6qTOe(rjBXOaCap8lFF8;Um_IlgoltC0LCIa6eXIG44b^7T_;j#UHqWi#Uao_z}l(uG_+^nV&2H)Ta4r4U6(iZ6J(l7EBJcG?xhnqTF-*pV*Q+y_V(H$k}aQTbzHqMKn zHtM{IDs?*eN5I-~)`{71J-tZZlZXFoF+-w#>=e$bP(r(|7?lXIy?7 zZpL<@?RB9wGqN;top^fglCj8)>BpNw>-ww;&BDljaT$M&6&aM*Emq(wd?bS}KCO|f z@SV7f`_hWZfj(>#F|0~cP#PmQ;(O7UE;_44EF0S`pj{)k;Bzc&x8naH3q?#@+Bvx$ zBX{C}e0oKlX1<8+*3OfKH*8-OME6HhZJi7qFbymLu0+3k&DDY zXi0r`3Xi5y&&VMSo=|g~0d;ykwMO2BtzD5*Y_XYCEVUMImP96yjcA~wUM_f zn>($rO-wUmx{*(d?1qx&xKqs4W4e*K=dKix&6EF38aXJ#8MQgYI+Z#5Nh3GtP6kA; zag*?F%E-1SeM-W+Nh2T0QAp8QOBlHn%ktGyXzs<*1P|q{qz8B?Q4ZW@!RkcJ$&{pH zWrF+iR?!12OK^AIDtdrLiL!s41%rtg^(je5e2e^>n=e$+)0KX(+B~(c|PA6goR7pCHCpeb3iXPxtg0o`L zcu9Ml!P&{4%{O@}DLCKq@8s9v9EB8}FZtKVBVzl4lGeB`yqhv|6i0KDQ(TU!Y(i2! z`twOXS_;jSXVpd?(&a5)3eF|r8KxU~O=RttG{*r|BWJY(yYGn|pGs!us+t8%wMJgV z!LG?EE(e8IQ`DPk*n_dI$SEdc*jxKyJtHp&GfV2TSL|*zjhQCDcH^gx$|)uzVh4r) zFq4sEcpej-QdB@DgeP@xd$Uc)4lA2O)$A9WMAfCyy!H@IWGbhaoX}vikVZz1;VE3s zN>Ks1EY={++LCD|)8Z7K#f=O^6^$Dr_LGecY&K=(3+yoW9zHun>6w1n zol3?(CoY-gV*D=8*~!t0hUFDa9eK-0r&l$c$E)H!37f=Iu^Sm3*F`GHrb^wfsxzvc zCEa>^NHy)ehNT(i#A{e);~sJ2uYNJmBC*rc0B)-scU3%HFN%4k>K6n3fM2_+x`uxM X6q4FH(I`LR00000NkvXXu0mjfT3V6~ literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/Contents.json b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/Contents.json new file mode 100644 index 000000000..da4a164c9 --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader0.imageset/Contents.json b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader0.imageset/Contents.json new file mode 100644 index 000000000..9f289f355 --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader0.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "loader_00000@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader0.imageset/loader_00000@2x.png b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader0.imageset/loader_00000@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2dbae73007f3b69152181f2556eecbdd0379a926 GIT binary patch literal 1615 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 literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader10.imageset/Contents.json b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader10.imageset/Contents.json new file mode 100644 index 000000000..d5f359473 --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader10.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "loader_00010@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader10.imageset/loader_00010@2x.png b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader10.imageset/loader_00010@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..86a98844607ddb8c474defe587b776cca0fac53e GIT binary patch literal 2035 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 literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader12.imageset/Contents.json b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader12.imageset/Contents.json new file mode 100644 index 000000000..157866258 --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader12.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "loader_00012@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader12.imageset/loader_00012@2x.png b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader12.imageset/loader_00012@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fb5ad2a3c6606b4e4e828ea83ddd81bff3dd23a6 GIT binary patch literal 2331 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 Th(xE800000NkvXXu0mjf(Ozsu literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader14.imageset/Contents.json b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader14.imageset/Contents.json new file mode 100644 index 000000000..75be39487 --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader14.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "loader_00014@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader14.imageset/loader_00014@2x.png b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader14.imageset/loader_00014@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c7a56154b83439940f3cb8d2cb04a57b1726532d GIT binary patch literal 2537 zcmVbVG7wVRUbD000P?b4y-7D@iRaYe_^wRCt{2oLg)i#TmzEW@mTL?zuU3>^QcQ7$+owkdTswqyqZTi>TBm zB0w#LR#p0tQi-Z+DV3MD2{>?BWv)n)HRWDFG&%8PX@ zQ3q192(MAJt=QbDrMnbu(Y({#AEeG@>Ynkdql^?dEry==+SEjA2tX1l-B{nQrtVF& z?$tBBN zQat7sF8cNuBbH#b@bl=k)*;%2jl1;h{bt8rEu$|%;zdv(PI;BT*wb&4!T@#3OH+Im z!ke*quhDv+(Y{4BmF0i5GNz0`N99`DnW5v2;(HqF#T%lF=Z#Sv7WPX&;CYMk<0W z{B0jL9!Yk7FTL&#ExnZWVCl3Ve7D}BKzQD_7EKzM2(*R(^kL(tEq#w9JHxy4)$GGI zq;6A_Iz(ff%y571=UY_s(Ny<0lWTi$0@h&R!4Q5*OJj&Wj7aVXwC+^2A7wT?lw1?u z)HTQ;yj3+*5DzhDn)_Q-^E;`Y2a_GE6|HuYVhDF?sRTqPy|Np6sSK-i0;2Dx*BwZ8 z*TSP0VM3)BClG)XfUhMxA22%>rOdSeLwLKEvIP4#DTOo@R_iYtZBJ%;vj~T@vqVg& z^k99LmbpvIw%5|57lI+&rY2AO)sLwg#!e`$S0VhH*3DZ~Gp3zB004k2!aa(fM3H4s zOCgDrHH!8(cP30E3AJ|bGun5msW^pRDIfrQwah-FJ&cjyTDKzgTd6Ls_F=kCNFil^ zs;f1`3K3lE2hEO~RWtnFp;15pZow)?Ey0Ed)cQ^>ooKQEGKT@t9xW4W zY(TwkQIjE$OdAvfD!a9Gu(3h(+M%X0P-(7E{Rt3&G{SvLxbC@qaGr)|1SmP3+kWfNG#?^*~y4Kc2$Q`h*C6DbU4Z5Uu-t`>G{K zO#%V@GK)*=xe8j|l&(#I7^7s8c>%@-(V7T;!MD7o4B4*W@B7tYV*}>bCrHVTsLHLe za5y^=v?wQ_*2hSp5NW+^L%@NU;9lSYsDN4zQ}>it@tbUg^n^I+Rc1da-drxh_vlBQ z>1NADY{6c!@_~m3*ZP=S7-wGdgb@zJIp2QQs|2P%l@Vx7fjH;e_nE8HadmRUNk6ss&s>P44=kGd#v$q)nC*|mR9#UO?E8g**>FqZ zJkiveasVcnmw@O_JyVNT!xe!6@lW8`<$+!1Fw!u4<= zwemY#@B!u$A-1SyrV->GW#nKb_oAJj4tni!U26Cpw*?zyjt|6U)u`v#&43u9?xAY# z4|aYkP%*+1sck&91RJCd5xf^0S%m8_?`A-J;90+|jJ|45PSwn#=cxJGWeGMwomuX$ zQxffpT32#=f}ioNXDXwwIa5Uu%|`qh#E~c1f)7wH=p011> zb!UUsLN1q>axxEyLFx=M(t>c8qOEuvS%K4|?#wgQ+&|rd3u3x5jW7SDKnzoNfI0}m z4N4;B$5s|H!MvC4i9^+~_q6*%qp?O{f`u-<`GC9d%83Vwo=eqJ6v;!Njx4RgEy$I5(>=T^&)d`p9< zPc>o)-z838vh%;HjJ!=s_6pUstXR;bK#Vf-k#FS~xlK)`5w4MYb07w(`^(D63)c8~ zKkm4(kQF`~DsXy{+NZo~r=qRLiO92WPw+oEQ$H(T{<}MyujQU_DXjcC91;97bx(Tb z93#86OoY#pj4|?5Y3Mm?{6o*GhceHV*BSsI0GQ$aIcool6gOfc@FPD9dCi{sVQKIm zZefc1byAmA7hAY_6ad#@{Y#0qCo>y5f<7xbM4ew(MvpktdFIts{aao5^*jQABB$ql z`%O~RA=;rWufE3;>=k?RvEqM@lhSP6xbr;q<=68l0A>-sN6-Ewd($>Gxs)MqxrL`I zqbI#`q5f2!qfWJ+LjkZu(Y|7K{2;Ub8czaW@a<=-xx>!XH1q2!Xe^?xwVne3xE|}@ zPIW(Iu4z+L2ml0703iUFVg5^Y{@H47gp&I2w`>5d=jp@717^n^S}FlifzvZy^{>wK zrO@T05{X12kw_#Gi9{liNF)-8L?V$$B(d;c1VR`zM?h}K00000NkvXXu0mjf*8jXl literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader15.imageset/Contents.json b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader15.imageset/Contents.json new file mode 100644 index 000000000..becd661a6 --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader15.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "loader_00015@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader15.imageset/loader_00015@2x.png b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader15.imageset/loader_00015@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..175a6e312b8042b3ef09989756e887ce55661f38 GIT binary patch literal 2515 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 FV1iU6UMv6r literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader19.imageset/Contents.json b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader19.imageset/Contents.json new file mode 100644 index 000000000..58c1bd721 --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader19.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "loader_00019@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader19.imageset/loader_00019@2x.png b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader19.imageset/loader_00019@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5804aa280d115f56001f30f7910e523b08dcb9d3 GIT binary patch literal 2112 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 Q{{R3007*qoM6N<$g6cNX00000 literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader22.imageset/Contents.json b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader22.imageset/Contents.json new file mode 100644 index 000000000..a54612636 --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader22.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "loader_00022@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader22.imageset/loader_00022@2x.png b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader22.imageset/loader_00022@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..64b23dfcbe8a2aabec73e24b21ddc546c1161ed7 GIT binary patch literal 1852 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 literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader28.imageset/Contents.json b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader28.imageset/Contents.json new file mode 100644 index 000000000..98cb1000e --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader28.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "loader_00028@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader28.imageset/loader_00028@2x.png b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader28.imageset/loader_00028@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..503443f16d7207b0d0a15e5d4d75f6480a8585ee GIT binary patch literal 1615 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 literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader7.imageset/Contents.json b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader7.imageset/Contents.json new file mode 100644 index 000000000..e14a86f3a --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader7.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "loader_00007@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader7.imageset/loader_00007@2x.png b/Sample/OCKSampleWatch/Base.lproj/Images.xcassets/loader_sequence/loader7.imageset/loader_00007@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0a3e1d52254c77bf1bc2402a3caa5839a991f792 GIT binary patch literal 1786 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 Us-A5x%>V!Z07*qoM6N<$g76&0o&W#< literal 0 HcmV?d00001 diff --git a/Sample/OCKSampleWatch/Base.lproj/Interface.storyboard b/Sample/OCKSampleWatch/Base.lproj/Interface.storyboard new file mode 100644 index 000000000..bf1cd1ee3 --- /dev/null +++ b/Sample/OCKSampleWatch/Base.lproj/Interface.storyboard @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+
+ +
+
+ +
diff --git a/Sample/OCKSampleWatch/Info.plist b/Sample/OCKSampleWatch/Info.plist new file mode 100644 index 000000000..28c07672d --- /dev/null +++ b/Sample/OCKSampleWatch/Info.plist @@ -0,0 +1,35 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + OCKSample + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + + WKCompanionAppBundleIdentifier + com.example.apple-samplecode.CareKit + WKWatchKitApp + + + diff --git a/dependency b/dependency index 23900bed0..d84944ac6 160000 --- a/dependency +++ b/dependency @@ -1 +1 @@ -Subproject commit 23900bed0e5582a193dd6f6f72a0cb2afd303c35 +Subproject commit d84944ac6ade385fbbda5dd59066ebc438108cf3 diff --git a/testing/OCKTest/OCKTest.xcodeproj/project.pbxproj b/testing/OCKTest/OCKTest.xcodeproj/project.pbxproj index 7004e442c..8bc9d3064 100644 --- a/testing/OCKTest/OCKTest.xcodeproj/project.pbxproj +++ b/testing/OCKTest/OCKTest.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 2D365AEC1CDC150200B147FC /* Info-iPad.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2D365AEB1CDC150200B147FC /* Info-iPad.plist */; }; 2D365AF11CDC15A300B147FC /* BarChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DF2B6461CDC06F7003632BE /* BarChartViewController.swift */; }; 2D365AF21CDC15A300B147FC /* SymptomTrackerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DF2B64D1CDC06F7003632BE /* SymptomTrackerTableViewController.swift */; }; 2D365AF31CDC15A300B147FC /* InsightsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DF2B64B1CDC06F7003632BE /* InsightsTableViewController.swift */; }; @@ -20,9 +19,7 @@ 2D365AFB1CDC15A300B147FC /* CareKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD2F1201CD98F8300622794 /* CareKit.framework */; }; 2D365AFE1CDC15A300B147FC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2DF2B6591CDC075A003632BE /* Main.storyboard */; }; 2D365AFF1CDC15A300B147FC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2DF2B6611CDC07D6003632BE /* Assets.xcassets */; }; - 2D365B001CDC15A300B147FC /* Info-iPad.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2D365AEB1CDC150200B147FC /* Info-iPad.plist */; }; 2D365B011CDC15A300B147FC /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2DF2B6571CDC075A003632BE /* LaunchScreen.storyboard */; }; - 2D365B021CDC15A300B147FC /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2DF2B6691CDC07F5003632BE /* Info.plist */; }; 2D365B031CDC15A300B147FC /* OCKTest.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 2DF2B6661CDC07E3003632BE /* OCKTest.entitlements */; }; 2D365B051CDC15A300B147FC /* CareKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD2F1201CD98F8300622794 /* CareKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 2DD2F1231CD98F8A00622794 /* CareKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD2F1201CD98F8300622794 /* CareKit.framework */; }; @@ -40,7 +37,6 @@ 2DF2B65D1CDC075A003632BE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2DF2B6591CDC075A003632BE /* Main.storyboard */; }; 2DF2B6621CDC07D6003632BE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2DF2B6611CDC07D6003632BE /* Assets.xcassets */; }; 2DF2B6671CDC07E3003632BE /* OCKTest.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 2DF2B6661CDC07E3003632BE /* OCKTest.entitlements */; }; - 2DF2B66A1CDC07F5003632BE /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2DF2B6691CDC07F5003632BE /* Info.plist */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -247,7 +243,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0730; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = carekit.org; TargetAttributes = { 2D365AED1CDC15A300B147FC = { @@ -259,6 +255,7 @@ }; 2DBE4CEE1CD988E600B31591 = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0800; SystemCapabilities = { com.apple.HealthKit = { enabled = 1; @@ -316,9 +313,7 @@ files = ( 2D365AFE1CDC15A300B147FC /* Main.storyboard in Resources */, 2D365AFF1CDC15A300B147FC /* Assets.xcassets in Resources */, - 2D365B001CDC15A300B147FC /* Info-iPad.plist in Resources */, 2D365B011CDC15A300B147FC /* LaunchScreen.storyboard in Resources */, - 2D365B021CDC15A300B147FC /* Info.plist in Resources */, 2D365B031CDC15A300B147FC /* OCKTest.entitlements in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -329,9 +324,7 @@ files = ( 2DF2B65D1CDC075A003632BE /* Main.storyboard in Resources */, 2DF2B6621CDC07D6003632BE /* Assets.xcassets in Resources */, - 2D365AEC1CDC150200B147FC /* Info-iPad.plist in Resources */, 2DF2B65B1CDC075A003632BE /* LaunchScreen.storyboard in Resources */, - 2DF2B66A1CDC07F5003632BE /* Info.plist in Resources */, 2DF2B6671CDC07E3003632BE /* OCKTest.entitlements in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -444,8 +437,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -490,8 +485,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -510,6 +507,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -524,6 +522,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.carekit.OCKTest; PRODUCT_NAME = OCKTest; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -537,6 +536,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.carekit.OCKTest; PRODUCT_NAME = OCKTest; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/testing/OCKTest/OCKTest.xcodeproj/xcshareddata/xcschemes/OCKTest-iPad.xcscheme b/testing/OCKTest/OCKTest.xcodeproj/xcshareddata/xcschemes/OCKTest-iPad.xcscheme index 87e9bcf4d..794f1266d 100644 --- a/testing/OCKTest/OCKTest.xcodeproj/xcshareddata/xcschemes/OCKTest-iPad.xcscheme +++ b/testing/OCKTest/OCKTest.xcodeproj/xcshareddata/xcschemes/OCKTest-iPad.xcscheme @@ -1,6 +1,6 @@ + + + + + + + + + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/testing/OCKTest/OCKTest/AppDelegate.m b/testing/OCKTest/OCKTest/AppDelegate.m new file mode 100644 index 000000000..b8113470d --- /dev/null +++ b/testing/OCKTest/OCKTest/AppDelegate.m @@ -0,0 +1,68 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/testing/OCKTest/OCKTest/AppDelegate.swift b/testing/OCKTest/OCKTest/AppDelegate.swift index 80a385653..622c2d4a5 100644 --- a/testing/OCKTest/OCKTest/AppDelegate.swift +++ b/testing/OCKTest/OCKTest/AppDelegate.swift @@ -36,32 +36,40 @@ import UIKit class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? + + #if swift(>=3.0) + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { + return true + } - - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + #else + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: Any]?) -> Bool { // Override point for customization after application launch. return true } + + #endif - func applicationWillResignActive(application: UIApplication) { + func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - func applicationDidEnterBackground(application: UIApplication) { + func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - func applicationWillEnterForeground(application: UIApplication) { + func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - func applicationDidBecomeActive(application: UIApplication) { + func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - func applicationWillTerminate(application: UIApplication) { + func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } diff --git a/testing/OCKTest/OCKTest/Assets.xcassets/AppIcon.appiconset/Contents.json b/testing/OCKTest/OCKTest/Assets.xcassets/AppIcon.appiconset/Contents.json index eeea76c2d..1d060ed28 100644 --- a/testing/OCKTest/OCKTest/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/testing/OCKTest/OCKTest/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", @@ -30,6 +40,16 @@ "size" : "60x60", "scale" : "3x" }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, { "idiom" : "ipad", "size" : "29x29", diff --git a/testing/OCKTest/OCKTest/BarChartViewController.h b/testing/OCKTest/OCKTest/BarChartViewController.h new file mode 100644 index 000000000..5b87d854c --- /dev/null +++ b/testing/OCKTest/OCKTest/BarChartViewController.h @@ -0,0 +1,37 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +@interface BarChartViewController : UIViewController + +@end diff --git a/testing/OCKTest/OCKTest/BarChartViewController.m b/testing/OCKTest/OCKTest/BarChartViewController.m new file mode 100644 index 000000000..af4e01314 --- /dev/null +++ b/testing/OCKTest/OCKTest/BarChartViewController.m @@ -0,0 +1,182 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "BarChartViewController.h" + +@interface BarDataSource1 : NSObject + +@end + +@implementation BarDataSource1 + +- (NSInteger)numberOfCategoriesPerDataSeriesInChartView:(OCKGroupedBarChartView *)chartView { + return 5; +} + +- (NSInteger)numberOfDataSeriesInChartView:(OCKGroupedBarChartView *)chartView { + return 4; +} + +- (UIColor *)chartView:(OCKGroupedBarChartView *)chartView colorForDataSeriesAtIndex:(NSUInteger)dataSeriesIndex { + + return @[ + [[UIColor redColor] colorWithAlphaComponent:0.5], + [[UIColor orangeColor] colorWithAlphaComponent:0.5], + [[UIColor purpleColor] colorWithAlphaComponent:0.5], + [[UIColor brownColor] colorWithAlphaComponent:0.5] + ][dataSeriesIndex]; +} + +- (NSString *)chartView:(OCKGroupedBarChartView *)chartView nameForDataSeriesAtIndex:(NSUInteger)dataSeriesIndex { + return [NSString stringWithFormat:@"Data Series Index %@", @(dataSeriesIndex)]; +} + +- (NSNumber *)chartView:(OCKGroupedBarChartView *)chartView valueForCategoryAtIndex:(NSUInteger)categoryIndex inDataSeriesAtIndex:(NSUInteger)dataSeriesIndex { + if (dataSeriesIndex == 1 && categoryIndex == 1) { + return @(-1); + } + return @(dataSeriesIndex); +} + +- (NSString *)chartView:(OCKGroupedBarChartView *)chartView valueStringForCategoryAtIndex:(NSUInteger)categoryIndex inDataSeriesAtIndex:(NSUInteger)dataSeriesIndex { + if (dataSeriesIndex == 1 && categoryIndex == 1) { + return @"-1"; + } + return [@(dataSeriesIndex) description]; +} + +- (NSString *)chartView:(OCKGroupedBarChartView *)chartView titleForCategoryAtIndex:(NSUInteger)categoryIndex { + return [NSString stringWithFormat:@"Group %@", @(categoryIndex)]; +} + +- (NSString *)chartView:(OCKGroupedBarChartView *)chartView subtitleForCategoryAtIndex:(NSUInteger)categoryIndex { + return [NSString stringWithFormat:@"sub %@", @(categoryIndex)]; +} + +- (NSNumber *)maximumScaleRangeValueOfChartView:(OCKGroupedBarChartView *)chartView { + return @8; +} + +- (NSNumber *)minimumScaleRangeValueOfChartView:(OCKGroupedBarChartView *)chartView { + return @(-8); +} + +@end + +@interface BarDataSource2 : NSObject + +@end + +@implementation BarDataSource2 + +- (NSInteger)numberOfCategoriesPerDataSeriesInChartView:(OCKGroupedBarChartView *)chartView { + return 5; +} + +- (NSInteger)numberOfDataSeriesInChartView:(OCKGroupedBarChartView *)chartView { + return 4; +} + +- (UIColor *)chartView:(OCKGroupedBarChartView *)chartView colorForDataSeriesAtIndex:(NSUInteger)dataSeriesIndex { + + return @[ + [[UIColor redColor] colorWithAlphaComponent:0.5], + [[UIColor orangeColor] colorWithAlphaComponent:0.5], + [[UIColor purpleColor] colorWithAlphaComponent:0.5], + [[UIColor brownColor] colorWithAlphaComponent:0.5] + ][dataSeriesIndex]; +} + +- (NSString *)chartView:(OCKGroupedBarChartView *)chartView nameForDataSeriesAtIndex:(NSUInteger)dataSeriesIndex { + return [NSString stringWithFormat:@"Data Series Index %@", @(dataSeriesIndex)]; +} + +- (NSNumber *)chartView:(OCKGroupedBarChartView *)chartView valueForCategoryAtIndex:(NSUInteger)categoryIndex inDataSeriesAtIndex:(NSUInteger)dataSeriesIndex { + return @(dataSeriesIndex + 10000000); +} + +- (NSString *)chartView:(OCKGroupedBarChartView *)chartView valueStringForCategoryAtIndex:(NSUInteger)categoryIndex inDataSeriesAtIndex:(NSUInteger)dataSeriesIndex { + return [@(dataSeriesIndex + 10000000) description]; +} + +- (NSString *)chartView:(OCKGroupedBarChartView *)chartView titleForCategoryAtIndex:(NSUInteger)categoryIndex { + return [NSString stringWithFormat:@"Group %@", @(categoryIndex)]; +} + +- (NSString *)chartView:(OCKGroupedBarChartView *)chartView subtitleForCategoryAtIndex:(NSUInteger)categoryIndex { + return [NSString stringWithFormat:@"sub %@", @(categoryIndex)]; +} + +- (NSNumber *)maximumScaleRangeValueOfChartView:(OCKGroupedBarChartView *)chartView { + return @(3 + 10000000); +} + +- (NSNumber *)minimumScaleRangeValueOfChartView:(OCKGroupedBarChartView *)chartView { + return @(-1 + 10000000); +} + +@end + + +@implementation BarChartViewController { + BarDataSource1 *_dataSource1; + BarDataSource2 *_dataSource2; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + self.title = @"BarChartView"; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + + OCKGroupedBarChartView *barChartView = [[OCKGroupedBarChartView alloc] init]; + _dataSource1 = [BarDataSource1 new]; + barChartView.dataSource = _dataSource1; + barChartView.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.1]; + CGSize size = [barChartView systemLayoutSizeFittingSize:CGSizeMake(self.view.bounds.size.width - 20, 1) withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityFittingSizeLevel]; + barChartView.frame = CGRectMake(10, 80, size.width, size.height); + [self.view addSubview:barChartView]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [barChartView animateWithDuration:1.5]; + }); + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + _dataSource2 = [BarDataSource2 new]; + barChartView.dataSource = _dataSource2; + [barChartView animateWithDuration:1.5]; + }); +} + +@end diff --git a/testing/OCKTest/OCKTest/BarChartViewController.swift b/testing/OCKTest/OCKTest/BarChartViewController.swift index 7d2490c89..284327ad5 100644 --- a/testing/OCKTest/OCKTest/BarChartViewController.swift +++ b/testing/OCKTest/OCKTest/BarChartViewController.swift @@ -39,29 +39,29 @@ class BarChartViewController: UIViewController, OCKGroupedBarChartViewDataSource override func viewDidLoad() { super.viewDidLoad() - let chartWidth = UIScreen.mainScreen().bounds.width - 20 + let chartWidth = UIScreen.main.bounds.width - 20 scrollView.contentSize = CGSize(width: self.view.frame.width, height: 2000) - let multiColorChartView = OCKGroupedBarChartView.init(frame: CGRectMake(5, 0, chartWidth, 600)) + let multiColorChartView = OCKGroupedBarChartView.init(frame: CGRect(x: 5, y: 0, width: chartWidth, height: 600)) multiColorChartView.accessibilityLabel = "multiColorChartView" - multiColorChartView.animateWithDuration(4) + multiColorChartView.animate(withDuration: 4) multiColorChartView.backgroundColor = UIColor.init(hue: 0.85, saturation: 0.1, brightness: 0.8, alpha: 0.3) multiColorChartView.dataSource = self scrollView.addSubview(multiColorChartView) - let emptyChartView = OCKGroupedBarChartView.init(frame: CGRectMake(5, 610, chartWidth, 20)) + let emptyChartView = OCKGroupedBarChartView.init(frame: CGRect(x: 5, y: 610, width: chartWidth, height: 20)) emptyChartView.accessibilityLabel = "emptyChartView" emptyChartView.backgroundColor = UIColor.init(hue: 0.1, saturation: 0.8, brightness: 0.5, alpha: 0.8) scrollView.addSubview(emptyChartView) - let twoSeriesChartView = OCKGroupedBarChartView.init(frame: CGRectMake(5, 640, chartWidth, 500)) + let twoSeriesChartView = OCKGroupedBarChartView.init(frame: CGRect(x: 5, y: 640, width: chartWidth, height: 500)) twoSeriesChartView.accessibilityLabel = "twoSeriesChartView" twoSeriesChartView.backgroundColor = UIColor.init(hue: 0.05, saturation: 0.1, brightness: 0.9, alpha: 0.3) twoSeriesChartView.dataSource = self - twoSeriesChartView.animateWithDuration(1) + twoSeriesChartView.animate(withDuration: 1) scrollView.addSubview(twoSeriesChartView) - let negativeValuesChartView = OCKGroupedBarChartView.init(frame: CGRectMake(5, 1200, chartWidth, 600)) + let negativeValuesChartView = OCKGroupedBarChartView.init(frame: CGRect(x: 5, y: 1200, width: chartWidth, height: 600)) negativeValuesChartView.backgroundColor = UIColor.init(hue: 0.66, saturation: 0.2, brightness: 0.9, alpha: 0.2) negativeValuesChartView.accessibilityLabel = "negativeValuesChartView" negativeValuesChartView.dataSource = self @@ -69,57 +69,57 @@ class BarChartViewController: UIViewController, OCKGroupedBarChartViewDataSource } - func numberOfDataSeriesInChartView(chartView: OCKGroupedBarChartView) -> Int { + func numberOfDataSeries(in chartView: OCKGroupedBarChartView) -> Int { let chartName = chartView.accessibilityLabel if chartName == "multiColorChartView" { return 30 } else if chartName == "negativeValuesChartView" { return 4 } else { return 2 } } - func numberOfCategoriesPerDataSeriesInChartView(chartView: OCKGroupedBarChartView) -> Int { + func numberOfCategoriesPerDataSeries(in chartView: OCKGroupedBarChartView) -> Int { let chartName = chartView.accessibilityLabel if chartName == "multiColorChartView" { return 1 } else if chartName == "negativeValuesChartView" { return 5 } else { return 8 } } - func maximumScaleRangeValueOfChartView(chartView: OCKGroupedBarChartView) -> NSNumber? { - if chartView.accessibilityLabel == "multiColorChartView" { return NSNumber(int: 1500) } + func maximumScaleRangeValue(of chartView: OCKGroupedBarChartView) -> NSNumber? { + if chartView.accessibilityLabel == "multiColorChartView" { return NSNumber(value: 1500) } return nil } - func minimumScaleRangeValueOfChartView(chartView: OCKGroupedBarChartView) -> NSNumber? { - if chartView.accessibilityLabel == "negativeValuesChartView" { return NSNumber(int: -40) } + func minimumScaleRangeValue(of chartView: OCKGroupedBarChartView) -> NSNumber? { + if chartView.accessibilityLabel == "negativeValuesChartView" { return NSNumber(value: -40) } return nil } - func chartView(chartView: OCKGroupedBarChartView, valueForCategoryAtIndex categoryIndex: UInt, inDataSeriesAtIndex dataSeriesIndex: UInt) -> NSNumber { + func chartView(_ chartView: OCKGroupedBarChartView, valueForCategoryAt categoryIndex: UInt, inDataSeriesAt dataSeriesIndex: UInt) -> NSNumber { let chartName = chartView.accessibilityLabel if chartName == "multiColorChartView" { - return (categoryIndex + 1) * (dataSeriesIndex*dataSeriesIndex + 1) + return NSNumber(value: (categoryIndex + 1) * (dataSeriesIndex*dataSeriesIndex + 1)) } else if chartName == "negativeValuesChartView" { var value:Int = (Int)((categoryIndex + 1) * (dataSeriesIndex + 1)) value = value * -1 - return value + return NSNumber(value: value) } else { - return NSNumber(float: Float(categoryIndex) * 0.04) + return NSNumber(value: Float(categoryIndex) * 0.04) } } - func chartView(chartView: OCKGroupedBarChartView, titleForCategoryAtIndex categoryIndex: UInt) -> String? { + func chartView(_ chartView: OCKGroupedBarChartView, titleForCategoryAt categoryIndex: UInt) -> String? { return "Title" + String(categoryIndex) } - func chartView(chartView: OCKGroupedBarChartView, subtitleForCategoryAtIndex categoryIndex: UInt) -> String? { + func chartView(_ chartView: OCKGroupedBarChartView, subtitleForCategoryAt categoryIndex: UInt) -> String? { return String(categoryIndex) + " SubTitle" } - func chartView(chartView: OCKGroupedBarChartView, colorForDataSeriesAtIndex dataSeriesIndex: UInt) -> UIColor { + func chartView(_ chartView: OCKGroupedBarChartView, colorForDataSeriesAt dataSeriesIndex: UInt) -> UIColor { let hue = ((CGFloat)(dataSeriesIndex + 1)) * 3 / 100.0 return UIColor.init(hue: hue, saturation: 0.7, brightness: 0.8, alpha: 1) } - func chartView(chartView: OCKGroupedBarChartView, nameForDataSeriesAtIndex dataSeriesIndex: UInt) -> String { + func chartView(_ chartView: OCKGroupedBarChartView, nameForDataSeriesAt dataSeriesIndex: UInt) -> String { return String(dataSeriesIndex) + " Series" } - func chartView(chartView: OCKGroupedBarChartView, valueStringForCategoryAtIndex categoryIndex: UInt, inDataSeriesAtIndex dataSeriesIndex: UInt) -> String? { - return "Val: " + String(chartView.dataSource!.chartView(chartView, valueForCategoryAtIndex: categoryIndex, inDataSeriesAtIndex: dataSeriesIndex)) + func chartView(_ chartView: OCKGroupedBarChartView, valueStringForCategoryAt categoryIndex: UInt, inDataSeriesAt dataSeriesIndex: UInt) -> String? { + return "Val: " + String(describing: chartView.dataSource!.chartView(chartView, valueForCategoryAt: categoryIndex, inDataSeriesAt: dataSeriesIndex)) } } diff --git a/testing/OCKTest/OCKTest/CareCardTableViewController.swift b/testing/OCKTest/OCKTest/CareCardTableViewController.swift index ff0893535..d658902b6 100644 --- a/testing/OCKTest/OCKTest/CareCardTableViewController.swift +++ b/testing/OCKTest/OCKTest/CareCardTableViewController.swift @@ -34,18 +34,18 @@ import CareKit class CareCardTableViewController: UITableViewController, OCKCarePlanStoreDelegate, OCKCareCardViewControllerDelegate { - override func numberOfSectionsInTableView(tableView: UITableView) -> Int { + override func numberOfSections(in tableView: UITableView) -> Int { return 1 } - override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 8 } - override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if let cell = tableView.dequeueReusableCellWithIdentifier("cell") { - switch indexPath.row { + if let cell = tableView.dequeueReusableCell(withIdentifier: "cell") { + switch (indexPath as NSIndexPath).row { case 0: cell.textLabel?.text = "Many Activities, Many Schedules" case 1: @@ -72,52 +72,53 @@ class CareCardTableViewController: UITableViewController, OCKCarePlanStoreDelega } - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let documentsDirectory = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true) + let documentsDirectory = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) - if indexPath.row == 0 { + if (indexPath as NSIndexPath).row == 0 { // Many Activities, Many Schedules - let startDateComponents = NSDateComponents.init() + var startDateComponents = DateComponents.init() startDateComponents.day = 20 startDateComponents.month = 2 startDateComponents.year = 2015 - let dailySchedule:OCKCareSchedule = OCKCareSchedule.dailyScheduleWithStartDate(startDateComponents, occurrencesPerDay: 2) - let weeklySchedule = OCKCareSchedule.weeklyScheduleWithStartDate(startDateComponents, occurrencesOnEachDay:[4, 0, 4, 0, 4, 0, 4]) - let alternateWeeklySchedule = OCKCareSchedule.weeklyScheduleWithStartDate(startDateComponents, occurrencesOnEachDay: [0, 1, 0, 0, 0, 0, 0], weeksToSkip: 1, endDate: nil) - let skipDaysSchedule = OCKCareSchedule.dailyScheduleWithStartDate(startDateComponents, occurrencesPerDay: 5, daysToSkip: 2, endDate: nil) + let dailySchedule:OCKCareSchedule = OCKCareSchedule.dailySchedule(withStartDate: startDateComponents, occurrencesPerDay: 2) + let weeklySchedule = OCKCareSchedule.weeklySchedule(withStartDate: startDateComponents, occurrencesOnEachDay:[4, 0, 4, 0, 4, 0, 4]) + let alternateWeeklySchedule = OCKCareSchedule.weeklySchedule(withStartDate: startDateComponents, occurrencesOnEachDay: [0, 1, 0, 0, 0, 0, 0], weeksToSkip: 1, endDate: nil) + let skipDaysSchedule = OCKCareSchedule.dailySchedule(withStartDate: startDateComponents, occurrencesPerDay: 5, daysToSkip: 2, endDate: nil) var carePlanActivities = [OCKCarePlanActivity]() let firstGroupId = "Group I1" - carePlanActivities.append(OCKCarePlanActivity.init(identifier: "Intervention Activity #1", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.Intervention, title: "Daily Intervention Activity Title 1", text: "Read the instructions about this task", tintColor: nil, instructions: "Perform the described task and report the results. Talk to your doctor if you need help", imageURL: nil, schedule: dailySchedule, resultResettable: true, userInfo: ["Key1":"Value1","Key2":"Value2"])) + carePlanActivities.append(OCKCarePlanActivity.init(identifier: "Intervention Activity #1", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.intervention, title: "Daily Intervention Activity Title 1", text: "Read the instructions about this task", tintColor: nil, instructions: "Perform the described task and report the results. Talk to your doctor if you need help", imageURL: nil, schedule: dailySchedule, resultResettable: true, userInfo: ["Key1":"Value1" as NSCoding,"Key2":"Value2" as NSCoding])) - carePlanActivities.append(OCKCarePlanActivity.init(identifier: "Intervention Activity #2", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.Intervention, title: "Alternate-Day Intervention Activity Title 2", text: "Complete this activity ASAP. No Instructions!", tintColor: UIColor.brownColor(), instructions: nil, imageURL: nil, schedule: weeklySchedule, resultResettable: true, userInfo: ["Key1":"Value1", "Key2":"Value2"])) + carePlanActivities.append(OCKCarePlanActivity.init(identifier: "Intervention Activity #2", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.intervention, title: "Alternate-Day Intervention Activity Title 2", text: "Complete this activity ASAP. No Instructions!", tintColor: UIColor.brown, instructions: nil, imageURL: nil, schedule: weeklySchedule, resultResettable: true, userInfo: ["Key1":"Value1" as NSCoding, "Key2":"Value2" as NSCoding])) - carePlanActivities.append(OCKCarePlanActivity.init(identifier: "Intervention Activity 3", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.Intervention, title: "Repeats Every Three Days", text: "This is a long line of text. It describes the Activity in detail", tintColor: UIColor.redColor(), instructions: LoremIpsum, imageURL: nil, schedule: skipDaysSchedule, resultResettable: false, userInfo:nil)) + carePlanActivities.append(OCKCarePlanActivity.init(identifier: "Intervention Activity 3", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.intervention, title: "Repeats Every Three Days", text: "This is a long line of text. It describes the Activity in detail", tintColor: UIColor.red, instructions: LoremIpsum, imageURL: nil, schedule: skipDaysSchedule, resultResettable: false, userInfo:nil)) - carePlanActivities.append(OCKCarePlanActivity.init(identifier: "Intervention Activity #4", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.Intervention, title: "Every other-Monday", text: "I am activity #4", tintColor: UIColor.greenColor(), instructions: nil, imageURL: nil, schedule: alternateWeeklySchedule, resultResettable: false, userInfo: nil)) + carePlanActivities.append(OCKCarePlanActivity.init(identifier: "Intervention Activity #4", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.intervention, title: "Every other-Monday", text: "I am activity #4", tintColor: UIColor.green, instructions: nil, imageURL: nil, schedule: alternateWeeklySchedule, resultResettable: false, userInfo: nil)) - carePlanActivities.append(OCKCarePlanActivity.init(identifier: "Intervention Activity #5", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.Intervention, title: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.", text: "This is the text", tintColor: nil, instructions: "Take pain medication", imageURL: nil, schedule: dailySchedule, resultResettable: false, userInfo: nil)) + carePlanActivities.append(OCKCarePlanActivity.init(identifier: "Intervention Activity #5", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.intervention, title: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.", text: "This is the text", tintColor: nil, instructions: "Take pain medication", imageURL: nil, schedule: dailySchedule, resultResettable: false, userInfo: nil)) - let activity6 = OCKCarePlanActivity.init(identifier: "Intervention Activity #6", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.Intervention, title: "Activity Ended Yesterday", text: LoremIpsum, tintColor: UIColor.grayColor(), instructions: LoremIpsum, imageURL: nil, schedule: dailySchedule, resultResettable: true, userInfo: nil) + let activity6 = OCKCarePlanActivity.init(identifier: "Intervention Activity #6", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.intervention, title: "Activity Ended Yesterday", text: LoremIpsum, tintColor: UIColor.gray, instructions: LoremIpsum, imageURL: nil, schedule: dailySchedule, resultResettable: true, userInfo: nil) carePlanActivities.append(activity6) - carePlanActivities.append(OCKCarePlanActivity.interventionWithIdentifier("Intervention Activity #7", groupIdentifier: nil, title: "No Group, No Text Activity", text: nil, tintColor: nil, instructions: nil, imageURL: nil, schedule: dailySchedule, userInfo: nil)) + carePlanActivities.append(OCKCarePlanActivity.intervention(withIdentifier: "Intervention Activity #7", groupIdentifier: nil, title: "No Group, No Text Activity", text: nil, tintColor: nil, instructions: nil, imageURL: nil, schedule: dailySchedule, userInfo: nil)) - carePlanActivities.append(OCKCarePlanActivity.interventionWithIdentifier("Intervention Activity #8", groupIdentifier: nil, title: "", text: "Missing Title", tintColor: UIColor.purpleColor(), instructions: "Some Instructions", imageURL: nil, schedule: dailySchedule, userInfo: ["":""])) + carePlanActivities.append(OCKCarePlanActivity.intervention(withIdentifier: "Intervention Activity #8", groupIdentifier: nil, title: "", text: "Missing Title", tintColor: UIColor.purple, instructions: "Some Instructions", imageURL: nil, schedule: dailySchedule, userInfo: ["":""])) - let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: NSURL.init(string: documentsDirectory[0])!) + let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: URL.init(string: documentsDirectory[0])!) for carePlanActivity in carePlanActivities { - carePlanStore.addActivity(carePlanActivity, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + carePlanStore.add(carePlanActivity, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) } - carePlanStore.setEndDate(NSDateComponents.init(date: NSDate().dateByAddingTimeInterval(-86400.0), calendar: NSCalendar.currentCalendar()), forActivity: activity6, completion: { (boolVal, activity, error) in + let dateComponents = NSCalendar.current.dateComponents([.year, .month, .day, .era], from: Date().addingTimeInterval(-86400.0)) + carePlanStore.setEndDate(dateComponents, for: activity6, completion: { (boolVal, activity, error) in }) @@ -125,103 +126,104 @@ class CareCardTableViewController: UITableViewController, OCKCarePlanStoreDelega careCardController.showEdgeIndicators = true self.navigationController?.pushViewController(careCardController, animated: true) - } else if indexPath.row == 1 { + } else if (indexPath as NSIndexPath).row == 1 { // With Delegate & Images - let dateComponents = NSDateComponents.init(year: 2015, month: 2, day: 20) - let schedule = OCKCareSchedule.dailyScheduleWithStartDate(dateComponents, occurrencesPerDay: 6) + let dateComponents = DateComponents.init(year: 2015, month: 2, day: 20) + let schedule = OCKCareSchedule.dailySchedule(withStartDate: dateComponents, occurrencesPerDay: 6) - let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first! - let imageFileURL = documentsURL.URLByAppendingPathComponent("Triangles.jpg") + let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + let imageFileURL = documentsURL.appendingPathComponent("Triangles.jpg") let secondGroupId = "Group I2" - let carePlanActivity1 = OCKCarePlanActivity.init(identifier: "Intervention Activity 1", groupIdentifier: secondGroupId, type: OCKCarePlanActivityType.Intervention, title: "1. This is the first Intervention Activity", text: "", tintColor: UIColor.redColor(), instructions: "No instructions required", imageURL: imageFileURL, schedule: schedule, resultResettable: true, userInfo: ["Key1":"Value1","Key2":"Value2"]) + let carePlanActivity1 = OCKCarePlanActivity.init(identifier: "Intervention Activity 1", groupIdentifier: secondGroupId, type: OCKCarePlanActivityType.intervention, title: "1. This is the first Intervention Activity", text: "", tintColor: UIColor.red, instructions: "No instructions required", imageURL: imageFileURL, schedule: schedule, resultResettable: true, userInfo: ["Key1":"Value1" as NSCoding,"Key2":"Value2" as NSCoding]) - let carePlanActivity2 = OCKCarePlanActivity.init(identifier: "Intervention Activity 2", groupIdentifier: secondGroupId, type: OCKCarePlanActivityType.Intervention, title: "2. Another Intervention Activity", text: "Complete this activity ASAP. No Instructions!", tintColor: nil, instructions: nil, imageURL: imageFileURL, schedule: schedule, resultResettable: true, userInfo: nil) + let carePlanActivity2 = OCKCarePlanActivity.init(identifier: "Intervention Activity 2", groupIdentifier: secondGroupId, type: OCKCarePlanActivityType.intervention, title: "2. Another Intervention Activity", text: "Complete this activity ASAP. No Instructions!", tintColor: nil, instructions: nil, imageURL: imageFileURL, schedule: schedule, resultResettable: true, userInfo: nil) - let carePlanActivity3 = OCKCarePlanActivity.interventionWithIdentifier("Intervention Activity 3", groupIdentifier: secondGroupId, title: "3. Activity #3 is the last one", text: "Some Text", tintColor: UIColor.purpleColor(), instructions: "Some Instructions", imageURL: imageFileURL, schedule: schedule, userInfo: ["Key":"Val"]) + let carePlanActivity3 = OCKCarePlanActivity.intervention(withIdentifier: "Intervention Activity 3", groupIdentifier: secondGroupId, title: "3. Activity #3 is the last one", text: "Some Text", tintColor: UIColor.purple, instructions: "Some Instructions", imageURL: imageFileURL, schedule: schedule, userInfo: ["Key":"Val"]) - let dataPath = documentsDirectory[0].stringByAppendingString("/CarePlan2") - if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) { + let dataPath = documentsDirectory[0] + "/CarePlan2" + if !FileManager.default.fileExists(atPath: dataPath) { do { - try NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil) + try FileManager.default.createDirectory(atPath: dataPath, withIntermediateDirectories: false, attributes: nil) } catch(_) { assertionFailure("Unable to Create Directory for CarePlan2") } } - let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: NSURL.init(string: dataPath)!) + let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: URL.init(string: dataPath)!) carePlanStore.delegate = self - carePlanStore.addActivity(carePlanActivity1, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + carePlanStore.add(carePlanActivity1, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) - carePlanStore.addActivity(carePlanActivity2, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + carePlanStore.add(carePlanActivity2, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) - carePlanStore.addActivity(carePlanActivity3, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + carePlanStore.add(carePlanActivity3, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) let careCardController = OCKCareCardViewController.init(carePlanStore: carePlanStore) careCardController.maskImage = UIImage.init(named: "Stars") careCardController.smallMaskImage = UIImage.init(named: "Triangles.jpg") - careCardController.maskImageTintColor = UIColor.cyanColor() + careCardController.maskImageTintColor = UIColor.cyan careCardController.showEdgeIndicators = true self.navigationController?.pushViewController(careCardController, animated: true) - } else if indexPath.row == 2 { + } else if (indexPath as NSIndexPath).row == 2 { // No Activities - let dataPath = documentsDirectory[0].stringByAppendingString("/EmptyCarePlan") - if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) { + let dataPath = documentsDirectory[0] + "/EmptyCarePlan" + if !FileManager.default.fileExists(atPath: dataPath) { do { - try NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil) + try FileManager.default.createDirectory(atPath: dataPath, withIntermediateDirectories: false, attributes: nil) } catch(_) { assertionFailure("Unable to Create Directory for EmptyCarePlan") } } - let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: NSURL.init(string: dataPath)!) + let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: URL.init(string: dataPath)!) let careCardController = OCKCareCardViewController.init(carePlanStore: carePlanStore) - careCardController.maskImageTintColor = UIColor.orangeColor() + careCardController.maskImageTintColor = UIColor.orange self.navigationController?.pushViewController(careCardController, animated: true) - } else if indexPath.row == 3 { + } else if (indexPath as NSIndexPath).row == 3 { // Auto-Complete, No Edges - let startDateComponents = NSDateComponents.init(year: 2012, month: 12, day: 12) - let endDateComponents = NSDateComponents.init(year: 3000, month: 03, day: 30) - let schedule = OCKCareSchedule.dailyScheduleWithStartDate(startDateComponents, occurrencesPerDay: 5, daysToSkip: 0, endDate: endDateComponents) + let startDateComponents = DateComponents.init(year: 2012, month: 12, day: 12) + let endDateComponents = DateComponents.init(year: 3000, month: 03, day: 30) + let schedule = OCKCareSchedule.dailySchedule(withStartDate: startDateComponents, occurrencesPerDay: 5, daysToSkip: 0, endDate: endDateComponents) - let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first! - let imageFileURL = documentsURL.URLByAppendingPathComponent("Triangles.jpg") + let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + let imageFileURL = documentsURL.appendingPathComponent("Triangles.jpg") - let dataPath = documentsDirectory[0].stringByAppendingString("/CarePlanAuto") - if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) { + let dataPath = documentsDirectory[0] + "/CarePlanAuto" + if !FileManager.default.fileExists(atPath: dataPath) { do { - try NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil) + try FileManager.default.createDirectory(atPath: dataPath, withIntermediateDirectories: false, attributes: nil) } catch(_) { assertionFailure("Unable to Create Directory for CarePlanAuto") } } - let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: NSURL.init(string: dataPath)!) + let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: URL.init(string: dataPath)!) for index in 1...30 { - let carePlanActivity = OCKCarePlanActivity.init(identifier: "Intervention Activity" + String(index), groupIdentifier: "Group I2", type: OCKCarePlanActivityType.Intervention, title: "Activity Title"+String(index), text: "Text Text Text" + String(index), tintColor: UIColor.init(red: 0.2, green: 0.4, blue: 0.9, alpha: 0.4), instructions: "This is a set of instructions for activity #" + String(index), imageURL: imageFileURL, schedule: schedule, resultResettable: true, userInfo: nil) - carePlanStore.addActivity(carePlanActivity, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + let carePlanActivity = OCKCarePlanActivity.init(identifier: "Intervention Activity" + String(index), groupIdentifier: "Group I2", type: OCKCarePlanActivityType.intervention, title: "Activity Title"+String(index), text: "Text Text Text" + String(index), tintColor: UIColor.init(red: 0.2, green: 0.4, blue: 0.9, alpha: 0.4), instructions: "This is a set of instructions for activity #" + String(index), imageURL: imageFileURL, schedule: schedule, resultResettable: true, userInfo: nil) + carePlanStore.add(carePlanActivity, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) } - carePlanStore.eventsOnDate(NSDateComponents.init(date: NSDate(), calendar: NSCalendar.currentCalendar()), type: OCKCarePlanActivityType.Intervention, completion: { (allEventsArray, error) in + let dateComponents = NSCalendar.current.dateComponents([.year, .month, .day, .era], from: Date()) + carePlanStore.events(onDate: dateComponents, type: OCKCarePlanActivityType.intervention, completion: { (allEventsArray, error) in for activityEvents in allEventsArray { for event in activityEvents { - carePlanStore.updateEvent(event, withResult: nil, state: OCKCarePlanEventState.Completed, completion: { (boolVal, event, error) in + carePlanStore.update(event, with: nil, state: OCKCarePlanEventState.completed, completion: { (boolVal, event, error) in }) } } @@ -232,33 +234,33 @@ class CareCardTableViewController: UITableViewController, OCKCarePlanStoreDelega careCardController.maskImageTintColor = UIColor.init(red: 0.2, green: 0.4, blue: 0.9, alpha: 0.4) self.navigationController?.pushViewController(careCardController, animated: true) - } else if indexPath.row == 4 { + } else if (indexPath as NSIndexPath).row == 4 { // Activities don't complete - let dateComponents = NSDateComponents.init(year: 2015, month: 2, day: 20) - let schedule = OCKCareSchedule.dailyScheduleWithStartDate(dateComponents, occurrencesPerDay: 14) + let dateComponents = DateComponents.init(year: 2015, month: 2, day: 20) + let schedule = OCKCareSchedule.dailySchedule(withStartDate: dateComponents, occurrencesPerDay: 14) let fourthGroupId = "Group I4" - let carePlanActivity1 = OCKCarePlanActivity.init(identifier: "ActivityDoesntComplete1", groupIdentifier: fourthGroupId, type: OCKCarePlanActivityType.Intervention, title: "Does not Complete", text: "Tint color changes on tap", tintColor: UIColor.blueColor(), instructions: "No instructions required", imageURL: nil, schedule: schedule, resultResettable: true, userInfo:nil) - let carePlanActivity2 = OCKCarePlanActivity.init(identifier: "ActivityDoesntComplete2", groupIdentifier: fourthGroupId, type: OCKCarePlanActivityType.Intervention, title: "Does not Complete", text: "Tint color changes on tap", tintColor: UIColor.purpleColor(), instructions: "", imageURL: nil, schedule: schedule, resultResettable: true, userInfo:nil) + let carePlanActivity1 = OCKCarePlanActivity.init(identifier: "ActivityDoesntComplete1", groupIdentifier: fourthGroupId, type: OCKCarePlanActivityType.intervention, title: "Does not Complete", text: "Tint color changes on tap", tintColor: UIColor.blue, instructions: "No instructions required", imageURL: nil, schedule: schedule, resultResettable: true, userInfo:nil) + let carePlanActivity2 = OCKCarePlanActivity.init(identifier: "ActivityDoesntComplete2", groupIdentifier: fourthGroupId, type: OCKCarePlanActivityType.intervention, title: "Does not Complete", text: "Tint color changes on tap", tintColor: UIColor.purple, instructions: "", imageURL: nil, schedule: schedule, resultResettable: true, userInfo:nil) - let dataPath = documentsDirectory[0].stringByAppendingString("/CarePlanIncomplete") + let dataPath = documentsDirectory[0] + "/CarePlanIncomplete" - if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) { + if !FileManager.default.fileExists(atPath: dataPath) { do { - try NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil) + try FileManager.default.createDirectory(atPath: dataPath, withIntermediateDirectories: false, attributes: nil) } catch(_) { assertionFailure("Unable to Create Directory for CarePlanIncomplete") } } - let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: NSURL.init(string: dataPath)!) + let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: URL.init(string: dataPath)!) carePlanStore.delegate = self - carePlanStore.addActivity(carePlanActivity1, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + carePlanStore.add(carePlanActivity1, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) - carePlanStore.addActivity(carePlanActivity2, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + carePlanStore.add(carePlanActivity2, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) let careCardController = OCKCareCardViewController.init(carePlanStore: carePlanStore) @@ -267,103 +269,103 @@ class CareCardTableViewController: UITableViewController, OCKCarePlanStoreDelega careCardController.showEdgeIndicators = true self.navigationController?.pushViewController(careCardController, animated: true) - } else if indexPath.row == 5 { + } else if (indexPath as NSIndexPath).row == 5 { // Custom Details for Activities - let dataPath = documentsDirectory[0].stringByAppendingString("/CarePlan2") - if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) { + let dataPath = documentsDirectory[0] + "/CarePlan2" + if !FileManager.default.fileExists(atPath: dataPath) { return } - let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: NSURL.init(string: dataPath)!) + let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: URL.init(string: dataPath)!) let careCardController = OCKCareCardViewController.init(carePlanStore: carePlanStore) careCardController.delegate = self careCardController.showEdgeIndicators = true self.navigationController?.pushViewController(careCardController, animated: true) - } else if indexPath.row == 6 { + } else if (indexPath as NSIndexPath).row == 6 { // Save an Image - let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first! + let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! if let image = UIImage.init(named: "Triangles.jpg") { - let imageFileURL = documentsURL.URLByAppendingPathComponent("Triangles.jpg") + let imageFileURL = documentsURL.appendingPathComponent("Triangles.jpg") if let jpgImageData = UIImageJPEGRepresentation(image,0.5) { - jpgImageData.writeToURL(imageFileURL, atomically: false) + try? jpgImageData.write(to: imageFileURL, options: []) } } - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.greenColor() - tableView.cellForRowAtIndexPath(indexPath)?.selected = false + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.green + tableView.cellForRow(at: indexPath)?.isSelected = false - } else if indexPath.row == 7 { + } else if (indexPath as NSIndexPath).row == 7 { // Delete all Activites - tableView.cellForRowAtIndexPath(indexPath)?.selected = false + tableView.cellForRow(at: indexPath)?.isSelected = false - let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true) - let store = OCKCarePlanStore.init(persistenceDirectoryURL: NSURL.init(string: paths[0])!) - store.activitiesWithType(OCKCarePlanActivityType.Intervention, completion: { (boolVal, activities, error) in + let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) + let store = OCKCarePlanStore.init(persistenceDirectoryURL: URL.init(string: paths[0])!) + store.activities(with: OCKCarePlanActivityType.intervention, completion: { (boolVal, activities, error) in for activity:OCKCarePlanActivity in activities { - store.removeActivity(activity, completion: { (boolVal, error) in + store.remove(activity, completion: { (boolVal, error) in if boolVal == true { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.greenColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.green } else { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.redColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.red } - assert(boolVal, (error?.description)!) + assert(boolVal, (error?.localizedDescription)!) }) } }) - if NSFileManager.defaultManager().fileExistsAtPath(paths[0].stringByAppendingString("/CarePlan2")) { - let dataPath = NSURL.init(string:paths[0].stringByAppendingString("/CarePlan2")) + if FileManager.default.fileExists(atPath: paths[0] + "/CarePlan2") { + let dataPath = URL.init(string:paths[0] + "/CarePlan2") let store2 = OCKCarePlanStore.init(persistenceDirectoryURL: dataPath!) - store2.activitiesWithGroupIdentifier("Group I2", completion: { (boolVal, activities, error) in + store2.activities(withGroupIdentifier: "Group I2", completion: { (boolVal, activities, error) in for activity:OCKCarePlanActivity in activities { - store2.removeActivity(activity, completion: { (bool, error) in + store2.remove(activity, completion: { (bool, error) in if boolVal == true { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.greenColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.green } else { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.redColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.red } - assert(boolVal, (error?.description)!) + assert(boolVal, (error?.localizedDescription)!) }) } }) } - if NSFileManager.defaultManager().fileExistsAtPath(paths[0].stringByAppendingString("/CarePlanAuto")) { - let dataPath = NSURL.init(string:paths[0].stringByAppendingString("/CarePlanAuto")) + if FileManager.default.fileExists(atPath: paths[0] + "/CarePlanAuto") { + let dataPath = URL.init(string:paths[0] + "/CarePlanAuto") let store3 = OCKCarePlanStore.init(persistenceDirectoryURL: dataPath!) - store3.activitiesWithCompletion({ (boolVal, activities, error) in + store3.activities(completion: { (boolVal, activities, error) in for activity in activities { - store3.removeActivity(activity, completion: { (boolVal, error) in + store3.remove(activity, completion: { (boolVal, error) in if boolVal == true { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.greenColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.green } else { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.redColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.red } - assert(boolVal, (error?.description)!) + assert(boolVal, (error?.localizedDescription)!) }) } }) } - if NSFileManager.defaultManager().fileExistsAtPath(paths[0].stringByAppendingString("/CarePlanIncomplete")) { - let dataPath = NSURL.init(string:paths[0].stringByAppendingString("/CarePlanIncomplete")) + if FileManager.default.fileExists(atPath: paths[0] + "/CarePlanIncomplete") { + let dataPath = URL.init(string:paths[0] + "/CarePlanIncomplete") let store4 = OCKCarePlanStore.init(persistenceDirectoryURL: dataPath!) - store4.activitiesWithCompletion({ (boolVal, activities, error) in + store4.activities(completion: { (boolVal, activities, error) in for activity in activities { - store4.removeActivity(activity, completion: { (boolVal, error) in + store4.remove(activity, completion: { (boolVal, error) in if boolVal == true { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.greenColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.green } else { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.redColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.red } - assert(boolVal, (error?.description)!) + assert(boolVal, (error?.localizedDescription)!) }) } }) @@ -371,60 +373,61 @@ class CareCardTableViewController: UITableViewController, OCKCarePlanStoreDelega } } - func careCardViewController(viewController: OCKCareCardViewController, shouldHandleEventCompletionForActivity interventionActivity: OCKCarePlanActivity) -> Bool { + func careCardViewController(_ viewController: OCKCareCardViewController, shouldHandleEventCompletionFor interventionActivity: OCKCarePlanActivity) -> Bool { if interventionActivity.groupIdentifier == "Group I4" { return false } return true } - func careCardViewController(viewController: OCKCareCardViewController, didSelectButtonWithInterventionEvent interventionEvent: OCKCarePlanEvent) { + func careCardViewController(_ viewController: OCKCareCardViewController, didSelectButtonWithInterventionEvent interventionEvent: OCKCarePlanEvent) { if interventionEvent.activity.groupIdentifier == "Group I4" { viewController.maskImageTintColor = interventionEvent.activity.tintColor } } - func careCardViewController(viewController: OCKCareCardViewController, didSelectRowWithInterventionActivity interventionActivity: OCKCarePlanActivity) { + func careCardViewController(_ viewController: OCKCareCardViewController, didSelectRowWithInterventionActivity interventionActivity: OCKCarePlanActivity) { if interventionActivity.groupIdentifier == "Group I2" { let detailsViewController = UIViewController.init() - detailsViewController.view.backgroundColor = UIColor.grayColor() - let textView = UITextView.init(frame: CGRectMake(30, 100, 300, 400)) - textView.backgroundColor = UIColor.whiteColor() - textView.editable = false + detailsViewController.view.backgroundColor = UIColor.gray + let textView = UITextView.init(frame: CGRect(x: 30, y: 100, width: 300, height: 400)) + textView.backgroundColor = UIColor.white + textView.isEditable = false var text = interventionActivity.title + "\n" - viewController.store.enumerateEventsOfActivity(interventionActivity, startDate: NSDateComponents.init(date: NSDate(), calendar: NSCalendar.currentCalendar()), endDate: NSDateComponents.init(date: NSDate(), calendar: NSCalendar.currentCalendar()), handler: + let dateComponents = NSCalendar.current.dateComponents([.year, .month, .day, .era], from: Date()) + viewController.store.enumerateEvents(of: interventionActivity, startDate: dateComponents, endDate: dateComponents, handler: { (event, stop) in - text = text.stringByAppendingString("Occurence #" + String(event!.occurrenceIndexOfDay)) - text = text.stringByAppendingString(" : State " + String(event!.state.rawValue) + "\n") + text = text + ("Occurence #" + String(event!.occurrenceIndexOfDay)) + text = text + (" : State " + String(event!.state.rawValue) + "\n") }, completion: { (completed, error) in if completed == true { - dispatch_async(dispatch_get_main_queue()){ + DispatchQueue.main.async{ textView.text = text detailsViewController.view.addSubview(textView) viewController.navigationController?.pushViewController(detailsViewController, animated: true) } } else { - assert(completed, (error?.description)!) + assert(completed, (error?.localizedDescription)!) } }) } } - func carePlanStoreActivityListDidChange(store: OCKCarePlanStore) { + func carePlanStoreActivityListDidChange(_ store: OCKCarePlanStore) { print("carePlanStoreActivityListDidChange") } - func carePlanStore(store: OCKCarePlanStore, didReceiveUpdateOfEvent event: OCKCarePlanEvent) { + func carePlanStore(_ store: OCKCarePlanStore, didReceiveUpdateOf event: OCKCarePlanEvent) { print("Care Event Details\n") print("Occurence: " + String(event.occurrenceIndexOfDay)) print("Days Since Start: " + String(event.numberOfDaysSinceStart)) - print("Date: " + String(event.date)) + print("Date: " + String(describing: event.date)) print("Activity: " + String(event.activity.title)) print("State: " + String(event.state.rawValue)) - print("Result: " + String(event.result)) + print("Result: " + String(describing: event.result)) } } diff --git a/testing/OCKTest/OCKTest/ConnectTableViewController.swift b/testing/OCKTest/OCKTest/ConnectTableViewController.swift index 730e7437a..863081acc 100644 --- a/testing/OCKTest/OCKTest/ConnectTableViewController.swift +++ b/testing/OCKTest/OCKTest/ConnectTableViewController.swift @@ -35,17 +35,17 @@ import CareKit class ConnectTableViewController: UITableViewController, OCKConnectViewControllerDelegate { - override func numberOfSectionsInTableView(tableView: UITableView) -> Int { + override func numberOfSections(in tableView: UITableView) -> Int { return 1 } - override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 5 } - override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { - if let cell = tableView.dequeueReusableCellWithIdentifier("cell") { - switch indexPath.row { + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if let cell = tableView.dequeueReusableCell(withIdentifier: "cell") { + switch (indexPath as NSIndexPath).row { case 0: cell.textLabel?.text = "No Delegate" case 1: @@ -65,71 +65,71 @@ class ConnectTableViewController: UITableViewController, OCKConnectViewControlle } } - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { - if indexPath.row == 0 { + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if (indexPath as NSIndexPath).row == 0 { // No Delegate - let contact1 = OCKContact(contactType: .CareTeam, name: "Anne Johnson", relation: "Primary Physician @ Nearby Hospital in my State", contactInfoItems: [.email("annejohnson1@mac.com")], tintColor: .purpleColor(), monogram: "AJ", image: nil) - let contact2 = OCKContact(contactType: .CareTeam, name: "Bill James, Lorem Ipsum dolor", relation: "Doctor", contactInfoItems: [.phone("1-888-555-5512"), .email("this_is_a_very_long_username@example.com")], tintColor: nil, monogram: "Bill James, Lorem Ipsum dolor", image: nil) - let contact3 = OCKContact(contactType: .Personal, name: "Maria Ruiz", relation: "Friend", contactInfoItems: [], tintColor: .greenColor(), monogram: "MR", image: nil) - let contact4 = OCKContact(contactType: .Personal, name: "Ravi Patel", relation: "Emergency Contact", contactInfoItems: [.phone("8885555512"), .email("888-555-5512")], tintColor: .orangeColor(), monogram: "RP",image: UIImage(named: "Stars")) - let contact5 = OCKContact(contactType: .Personal, name: "", relation: "", contactInfoItems: [], tintColor: nil, monogram: "", image: nil) + let contact1 = OCKContact(contactType: .careTeam, name: "Anne Johnson", relation: "Primary Physician @ Nearby Hospital in my State", contactInfoItems: [.email("annejohnson1@mac.com")], tintColor: .purple, monogram: "AJ", image: nil) + let contact2 = OCKContact(contactType: .careTeam, name: "Bill James, Lorem Ipsum dolor", relation: "Doctor", contactInfoItems: [.phone("1-888-555-5512"), .email("this_is_a_very_long_username@example.com")], tintColor: nil, monogram: "Bill James, Lorem Ipsum dolor", image: nil) + let contact3 = OCKContact(contactType: .personal, name: "Maria Ruiz", relation: "Friend", contactInfoItems: [], tintColor: .green, monogram: "MR", image: nil) + let contact4 = OCKContact(contactType: .personal, name: "Ravi Patel", relation: "Emergency Contact", contactInfoItems: [.phone("8885555512"), .email("888-555-5512")], tintColor: .orange, monogram: "RP",image: UIImage(named: "Stars")) + let contact5 = OCKContact(contactType: .personal, name: "", relation: "", contactInfoItems: [], tintColor: nil, monogram: "", image: nil) let connectViewController = OCKConnectViewController(contacts: [contact1, contact2, contact3, contact4, contact5]) self.navigationController?.pushViewController(connectViewController, animated: true) - } else if indexPath.row == 1 { + } else if (indexPath as NSIndexPath).row == 1 { // With Delegate & Edge Indicators - let contact1 = OCKContact(contactType: .CareTeam, name: "Dr Kumar, Gita", relation: "Nutritionist", contactInfoItems: [.email("gkumar@mac.com")], tintColor: .blueColor(), monogram: "GK", image: nil) + let contact1 = OCKContact(contactType: .careTeam, name: "Dr Kumar, Gita", relation: "Nutritionist", contactInfoItems: [.email("gkumar@mac.com")], tintColor: .blue, monogram: "GK", image: nil) contact1.image = UIImage(named: "SquareCircle") - let contact2Info: [OCKContactInfo] = [OCKContactInfo(type: .Phone, displayString: "888-555-5512", actionURL: nil), - OCKContactInfo(type: .Message, displayString: "888-555-5512", actionURL: nil), - OCKContactInfo(type: .Email, displayString: "drTomClark@example.com", actionURL: nil)] - let contact2 = OCKContact(contactType: .CareTeam, name: "Dr Tom Clark", relation: "Physician", contactInfoItems: contact2Info, tintColor: nil, monogram: "TC", image: nil) - let contact3 = OCKContact(contactType: .CareTeam, name: "Dr Juan Chavez", relation: "Dentist", contactInfoItems: [.sms("888-555-5512")], tintColor: .greenColor(), monogram: "JC", image: nil) - let contact4 = OCKContact(contactType: .Personal, name: "Jason", relation: "Dad", contactInfoItems: [.phone("888-555-5512"), .sms("888-555-5512"), .email("dad@example.com")], tintColor: .orangeColor(), monogram: "Dad" , image: UIImage(named: "SquareCircle")) - let contact5 = OCKContact(contactType: .Personal, name: "Mei Chen", relation: "Sis", contactInfoItems: [], tintColor: nil, monogram: "MC", image: UIImage(named: "Triangles.jpg")) - let contact6 = OCKContact(contactType: .Personal, name: "Avram", relation: "Bro", contactInfoItems: [.email("avram@example.com")], tintColor: nil, monogram: "Avram", image: nil) - let contact7 = OCKContact(contactType: .Personal, name: "Jim", relation: "Best Friend", contactInfoItems: [.email("jim12@example.com")], tintColor: nil, monogram: "😊" , image: nil) - let contact8 = OCKContact(contactType: .CareTeam, name: "Dr Yoshiko Wong", relation: "Doctor", contactInfoItems: [.sms("888-555-5512"), .email("drYoshiko@example.com")], tintColor: .cyanColor(), monogram: "YW", image: nil) + let contact2Info: [OCKContactInfo] = [OCKContactInfo(type: .phone, display: "888-555-5512", actionURL: nil), + OCKContactInfo(type: .message, display: "888-555-5512", actionURL: nil), + OCKContactInfo(type: .email, display: "drTomClark@example.com", actionURL: nil)] + let contact2 = OCKContact(contactType: .careTeam, name: "Dr Tom Clark", relation: "Physician", contactInfoItems: contact2Info, tintColor: nil, monogram: "TC", image: nil) + let contact3 = OCKContact(contactType: .careTeam, name: "Dr Juan Chavez", relation: "Dentist", contactInfoItems: [.sms("888-555-5512")], tintColor: .green, monogram: "JC", image: nil) + let contact4 = OCKContact(contactType: .personal, name: "Jason", relation: "Dad", contactInfoItems: [.phone("888-555-5512"), .sms("888-555-5512"), .email("dad@example.com")], tintColor: .orange, monogram: "Dad" , image: UIImage(named: "SquareCircle")) + let contact5 = OCKContact(contactType: .personal, name: "Mei Chen", relation: "Sis", contactInfoItems: [], tintColor: nil, monogram: "MC", image: UIImage(named: "Triangles.jpg")) + let contact6 = OCKContact(contactType: .personal, name: "Avram", relation: "Bro", contactInfoItems: [.email("avram@example.com")], tintColor: nil, monogram: "Avram", image: nil) + let contact7 = OCKContact(contactType: .personal, name: "Jim", relation: "Best Friend", contactInfoItems: [.email("jim12@example.com")], tintColor: nil, monogram: "😊" , image: nil) + let contact8 = OCKContact(contactType: .careTeam, name: "Dr Yoshiko Wong", relation: "Doctor", contactInfoItems: [.sms("888-555-5512"), .email("drYoshiko@example.com")], tintColor: .cyan, monogram: "YW", image: nil) let contact9Info: [OCKContactInfo] = [.phone("314-555-1234"), .phone("314-555-4321"), .email("ewodehouse@example.com"), .sms("314-555-4321"), - .facetimeVideo("user@example.com", displayString: nil), - .facetimeVideo("3145554321", displayString: "314-555-4321"), - .facetimeAudio("3145554321", displayString: "314-555-4321"), - OCKContactInfo(type: .Message, displayString: "ezra.wodehouse", actionURL: NSURL(string: "starstuffchat://ezra.wodehouse")!, label: "starstuff chat", icon: UIImage(named: "starstuff"))] - let contact9 = OCKContact(contactType: .CareTeam, name: "Dr Ezra Wodehouse", relation: "Doctor", contactInfoItems: contact9Info, tintColor: .brownColor(), monogram: "EW", image: nil) + .facetimeVideo("user@example.com", display: nil), + .facetimeVideo("3145554321", display: "314-555-4321"), + .facetimeAudio("3145554321", display: "314-555-4321"), + OCKContactInfo(type: .message, display: "ezra.wodehouse", actionURL: URL(string: "starstuffchat://ezra.wodehouse")!, label: "starstuff chat", icon: UIImage(named: "starstuff"))] + let contact9 = OCKContact(contactType: .careTeam, name: "Dr Ezra Wodehouse", relation: "Doctor", contactInfoItems: contact9Info, tintColor: .brown, monogram: "EW", image: nil) let connectViewController = OCKConnectViewController(contacts: [contact1, contact2, contact3, contact4, contact5, contact6, contact7, contact8, contact9]) connectViewController.delegate = self connectViewController.showEdgeIndicators = true self.navigationController?.pushViewController(connectViewController, animated: true) - } else if indexPath.row == 2 { + } else if (indexPath as NSIndexPath).row == 2 { // No Care Team - - let contact1 = OCKContact(contactType: .Personal, name: "Luisa", relation: "Friend", contactInfoItems: [.email("Luisa@example.com")], tintColor: nil, monogram: "Luisa", image: UIImage(named: "Triangles.jpg")) - let connectViewController = OCKConnectViewController(contacts: [contact1]) - connectViewController.delegate = self + + let contact1 = OCKContact(contactType: .personal, name: "Luisa", relation: "Friend", contactInfoItems:[.email("Luisa@example.com")], tintColor: nil, monogram: "Luisa", image: UIImage.init(named: "Triangles.jpg")) + let connectViewController = OCKConnectViewController.init(contacts: [contact1]) + connectViewController.delegate = self; self.navigationController?.pushViewController(connectViewController, animated: true) - } else if indexPath.row == 3 { + } else if (indexPath as NSIndexPath).row == 3 { // No Personal Contacts - let contact1 = OCKContact(contactType: .CareTeam, name: "Dr Gabrielle Contreras", relation: "Nutritionist", contactInfoItems: [.email("contreras@example.com")], tintColor: .blueColor(), monogram: "Not Visible", image: UIImage()) - let contact2 = OCKContact(contactType: .CareTeam, name: "Dr Scharanski", relation: "Dental Surgeon", contactInfoItems: [.sms("888-555-5512")], tintColor: .greenColor(), monogram: "Hello\nWorld", image: nil) + let contact1 = OCKContact(contactType: .careTeam, name: "Dr Gabrielle Contreras", relation: "Nutritionist", contactInfoItems: [.email("contreras@example.com")], tintColor: .blue, monogram: "Not Visible", image: UIImage()) + let contact2 = OCKContact(contactType: .careTeam, name: "Dr Scharanski", relation: "Dental Surgeon", contactInfoItems: [.sms("888-555-5512")], tintColor: .green, monogram: "Hello\nWorld", image: nil) let connectViewController = OCKConnectViewController(contacts: [contact1, contact2]) connectViewController.delegate = self; self.navigationController?.pushViewController(connectViewController, animated: true) - } else if indexPath.row == 4 { + } else if (indexPath as NSIndexPath).row == 4 { // No Contacts @@ -139,34 +139,34 @@ class ConnectTableViewController: UITableViewController, OCKConnectViewControlle } } - func connectViewController(connectViewController: OCKConnectViewController, titleForSharingCellForContact contact: OCKContact) -> String? { - if contact.type == .CareTeam { + func connectViewController(_ connectViewController: OCKConnectViewController, titleForSharingCellFor contact: OCKContact) -> String? { + if contact.type == .careTeam { return "Share Reports with a Doctor" } return nil } - func connectViewController(connectViewController: OCKConnectViewController, didSelectShareButtonForContact contact: OCKContact, presentationSourceView sourceView: UIView?) { + func connectViewController(_ connectViewController: OCKConnectViewController, didSelectShareButtonFor contact: OCKContact, presentationSourceView sourceView: UIView?) { - let bar1 = OCKBarSeries(title: "Title 1", values: [6, 5], valueLabels: ["6", "5"], tintColor: .brownColor()) - let bar2 = OCKBarSeries(title: "Title 2", values: [5, 10], valueLabels: ["5", "10"], tintColor: .blackColor()) - let bar3 = OCKBarSeries(title: "Title 3", values: [4, 10], valueLabels: ["4", "10"], tintColor: .blueColor()) + let bar1 = OCKBarSeries(title: "Title 1", values: [6, 5], valueLabels: ["6", "5"], tintColor: .brown) + let bar2 = OCKBarSeries(title: "Title 2", values: [5, 10], valueLabels: ["5", "10"], tintColor: .black) + let bar3 = OCKBarSeries(title: "Title 3", values: [4, 10], valueLabels: ["4", "10"], tintColor: .blue) - let chart = OCKBarChart(title: "Chart Title", text: "Chart Description", tintColor: .grayColor(), axisTitles: ["Axis #1", "Axis #2"], axisSubtitles: ["Subtitle #1", "Subtitle #2"], dataSeries: [bar1, bar2, bar3]) + let chart = OCKBarChart(title: "Chart Title", text: "Chart Description", tintColor: .gray, axisTitles: ["Axis #1", "Axis #2"], axisSubtitles: ["Subtitle #1", "Subtitle #2"], dataSeries: [bar1, bar2, bar3]) let doc = OCKDocument(title: nil, elements:[OCKDocumentElementChart(chart: chart)]) - doc.createPDFDataWithCompletion { (data, error) in + doc.createPDFData { (data, error) in let activityController = UIActivityViewController(activityItems: [data], applicationActivities: nil) - activityController.excludedActivityTypes = [UIActivityTypePostToVimeo, UIActivityTypeOpenInIBooks, UIActivityTypePostToFlickr] + activityController.excludedActivityTypes = [UIActivityType.postToVimeo, UIActivityType.openInIBooks, UIActivityType.postToFlickr] activityController.popoverPresentationController?.sourceView = sourceView - self.presentViewController(activityController, animated: true) {} + self.present(activityController, animated: true) {} } } - func connectViewController(connectViewController: OCKConnectViewController, handleContactInfoSelected contactInfo: OCKContactInfo) -> Bool { + func connectViewController(_ connectViewController: OCKConnectViewController, handleContactInfoSelected contactInfo: OCKContactInfo) -> Bool { if contactInfo.actionURL?.scheme == "starstuffchat" { print("starstuff chat pressed") return true diff --git a/testing/OCKTest/OCKTest/CustomChart.swift b/testing/OCKTest/OCKTest/CustomChart.swift index 0072c60f8..0793e392d 100644 --- a/testing/OCKTest/OCKTest/CustomChart.swift +++ b/testing/OCKTest/OCKTest/CustomChart.swift @@ -43,37 +43,37 @@ class CustomChart: OCKChart { chart.backgroundColor = self.tintColor chart.layer.cornerRadius = self.chartSize / 2.0 chart.layer.borderWidth = 5 - chart.layer.borderColor = UIColor.blackColor().CGColor + chart.layer.borderColor = UIColor.black.cgColor chart.translatesAutoresizingMaskIntoConstraints = false - chart.heightAnchor.constraintEqualToConstant(self.chartSize).active = true + chart.heightAnchor.constraint(equalToConstant: self.chartSize).isActive = true let topLeftbubble = UIView.init() - topLeftbubble.backgroundColor = UIColor.whiteColor() + topLeftbubble.backgroundColor = UIColor.white topLeftbubble.layer.cornerRadius = self.bubbleSize / 2.0 topLeftbubble.translatesAutoresizingMaskIntoConstraints = false chart.addSubview(topLeftbubble) - topLeftbubble.heightAnchor.constraintEqualToConstant(self.bubbleSize).active = true - topLeftbubble.widthAnchor.constraintEqualToConstant(self.bubbleSize).active = true - topLeftbubble.topAnchor.constraintEqualToAnchor(chart.topAnchor, constant: 50).active = true - topLeftbubble.leftAnchor.constraintEqualToAnchor(chart.leftAnchor, constant: 50).active = true + topLeftbubble.heightAnchor.constraint(equalToConstant: self.bubbleSize).isActive = true + topLeftbubble.widthAnchor.constraint(equalToConstant: self.bubbleSize).isActive = true + topLeftbubble.topAnchor.constraint(equalTo: chart.topAnchor, constant: 50).isActive = true + topLeftbubble.leftAnchor.constraint(equalTo: chart.leftAnchor, constant: 50).isActive = true let bottomRightBubble = UIView.init() - bottomRightBubble.backgroundColor = UIColor.whiteColor() + bottomRightBubble.backgroundColor = UIColor.white bottomRightBubble.layer.cornerRadius = self.bubbleSize / 2.0 bottomRightBubble.translatesAutoresizingMaskIntoConstraints = false chart.addSubview(bottomRightBubble) - bottomRightBubble.heightAnchor.constraintEqualToConstant(self.bubbleSize).active = true - bottomRightBubble.widthAnchor.constraintEqualToConstant(self.bubbleSize).active = true - bottomRightBubble.bottomAnchor.constraintEqualToAnchor(chart.bottomAnchor, constant: -50).active = true - bottomRightBubble.rightAnchor.constraintEqualToAnchor(chart.rightAnchor, constant: -50).active = true + bottomRightBubble.heightAnchor.constraint(equalToConstant: self.bubbleSize).isActive = true + bottomRightBubble.widthAnchor.constraint(equalToConstant: self.bubbleSize).isActive = true + bottomRightBubble.bottomAnchor.constraint(equalTo: chart.bottomAnchor, constant: -50).isActive = true + bottomRightBubble.rightAnchor.constraint(equalTo: chart.rightAnchor, constant: -50).isActive = true return chart } - override class func animateView(view: UIView, withDuration duration: NSTimeInterval) + override class func animate(_ view: UIView, withDuration duration: TimeInterval) { - UIView.animateWithDuration(duration, delay: 0, options: UIViewAnimationOptions.Autoreverse, animations: { + UIView.animate(withDuration: duration, delay: 0, options: UIViewAnimationOptions.autoreverse, animations: { view.alpha = 0 }) { (success) in view.alpha = 1 @@ -92,9 +92,9 @@ class CustomChart: OCKChart { self.bubbleSize = 20 super.init(coder: aDecoder) } - - override func copyWithZone(zone: NSZone) -> AnyObject { - let chart:CustomChart = super.copyWithZone(zone) as! CustomChart + + override func copy(with zone: NSZone? = nil) -> Any { + let chart:CustomChart = super.copy(with: zone) as! CustomChart chart.chartSize = self.chartSize chart.bubbleSize = self.bubbleSize return chart diff --git a/testing/OCKTest/OCKTest/DocumentViewController.h b/testing/OCKTest/OCKTest/DocumentViewController.h new file mode 100644 index 000000000..f8335490c --- /dev/null +++ b/testing/OCKTest/OCKTest/DocumentViewController.h @@ -0,0 +1,37 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +@interface DocumentViewController : UIViewController + +@end diff --git a/testing/OCKTest/OCKTest/DocumentViewController.m b/testing/OCKTest/OCKTest/DocumentViewController.m new file mode 100644 index 000000000..97d8aa5d7 --- /dev/null +++ b/testing/OCKTest/OCKTest/DocumentViewController.m @@ -0,0 +1,111 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "DocumentViewController.h" +#import + + +@implementation DocumentViewController { + OCKDocument *_document; + UIWebView *_webView; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.title = @"Test Document"; + + _webView = [UIWebView new]; + _webView.frame = self.view.bounds; + _webView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; + [self.view addSubview:_webView]; + + _document = [self createDocument]; + [_document createPDFDataWithCompletion:^(NSData * _Nonnull PDFdata, NSError * _Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + [_webView loadData:PDFdata MIMEType:@"application/pdf" textEncodingName:@"" baseURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@/", [NSUUID UUID].UUIDString]]]; + }); + + }]; +} + +- (OCKChart *)createBarChart { + OCKBarSeries *barSeries1 = [[OCKBarSeries alloc] initWithTitle:@"Bars 1" + values:@[@1, @2, @3, @4, @5] + valueLabels:@[@"1.0", @"2.0", @"3.0", @"4.0", @"5.0"] + tintColor:[[UIColor blueColor] colorWithAlphaComponent:0.2]]; + + OCKBarSeries *barSeries2 = [[OCKBarSeries alloc] initWithTitle:@"Bars 2" + values:@[@5, @4, @3, @2, @1] + valueLabels:@[@"5.0", @"4.0", @"3.0", @"2.0", @"1.0"] + tintColor:[[UIColor purpleColor] colorWithAlphaComponent:0.2]]; + + OCKBarChart *barChart = [[OCKBarChart alloc] initWithTitle:@"Title" + text:@"Text" + tintColor:[UIColor whiteColor] + axisTitles:@[@"Day1", @"Day2", @"Day3", @"Day4", @"Day5"] + axisSubtitles:@[@"M", @"T", @"W", @"T", @"F"] + dataSeries:@[barSeries1, barSeries2]]; + + return barChart; + +} + +- (UIImage *)createImageWithColor:(UIColor *)color { + CGSize size = CGSizeMake(200, 200); + UIGraphicsBeginImageContext(size); + [color setFill]; + [[UIBezierPath bezierPathWithRoundedRect:CGRectMake(10, 10, size.width - 20, size.height - 20) cornerRadius:20] fill]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; +} + +- (OCKDocument *)createDocument { + OCKDocumentElementSubtitle *subtitle = [[OCKDocumentElementSubtitle alloc] initWithSubtitle:@"First subtitle"]; + OCKDocumentElementParagraph *paragrah = [[OCKDocumentElementParagraph alloc] initWithContent:@"Lorem ipsum dolor sit amet, vim primis noster sententiae ne, et albucius apeirian accusata mea, vim at dicunt laoreet. Eu probo omnes inimicus ius, duo at veritus alienum. Nostrud facilisi id pro. Putant oporteat id eos. Admodum antiopam mel in, at per everti quaeque. Lorem ipsum dolor sit amet, vim primis noster sententiae ne, et albucius apeirian accusata mea, vim at dicunt laoreet. Eu probo omnes inimicus ius, duo at veritus alienum. Nostrud facilisi id pro. Putant oporteat id eos. Admodum antiopam mel in, at per everti quaeque. Lorem ipsum dolor sit amet, vim primis noster sententiae ne, et albucius apeirian accusata mea, vim at dicunt laoreet. Eu probo omnes inimicus ius, duo at veritus alienum. Nostrud facilisi id pro. Putant oporteat id eos. Admodum antiopam mel in, at per everti quaeque."]; + + OCKDocumentElementChart *barChart = [[OCKDocumentElementChart alloc] initWithChart:[self createBarChart]]; + OCKDocumentElementImage *imageElement1 = [[OCKDocumentElementImage alloc] initWithImage:[self createImageWithColor:[[UIColor redColor] colorWithAlphaComponent:0.2]]]; + OCKDocumentElementImage *imageElement2 = [[OCKDocumentElementImage alloc] initWithImage:[self createImageWithColor:[[UIColor yellowColor] colorWithAlphaComponent:0.2]]]; + OCKDocumentElementImage *imageElement3 = [[OCKDocumentElementImage alloc] initWithImage:[self createImageWithColor:[[UIColor blueColor] colorWithAlphaComponent:0.2]]]; + + OCKDocumentElementTable *table = [[OCKDocumentElementTable alloc] init]; + table.headers = @[@"Mon", @"Tue", @"Wed", @"Thu", @"Fri"]; + table.rows = @[@[@"1", @"2", @"3", @"4", @"5"], @[@"2", @"3", @"4", @"5", @"6"], @[@"3", @"4", @"5", @"6", @"7"]]; + + OCKDocument *doc = [[OCKDocument alloc] initWithTitle:@"This is a title" elements:@[subtitle, table, paragrah, barChart, paragrah, imageElement1, imageElement2, imageElement3, paragrah]]; + doc.pageHeader = @"App Name: ABC, User Name: John Appleseed"; + + return doc; +} + +@end diff --git a/testing/OCKTest/OCKTest/DocumentsTableViewController.swift b/testing/OCKTest/OCKTest/DocumentsTableViewController.swift index 97a4a4723..28c86d6e5 100644 --- a/testing/OCKTest/OCKTest/DocumentsTableViewController.swift +++ b/testing/OCKTest/OCKTest/DocumentsTableViewController.swift @@ -34,18 +34,18 @@ import CareKit class DocumentsTableViewController: UITableViewController { - override func numberOfSectionsInTableView(tableView: UITableView) -> Int { + override func numberOfSections(in tableView: UITableView) -> Int { return 1 } - override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 12 } - override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if let cell = tableView.dequeueReusableCellWithIdentifier("cell") { - switch indexPath.row { + if let cell = tableView.dequeueReusableCell(withIdentifier: "cell") { + switch (indexPath as NSIndexPath).row { case 0: cell.textLabel?.text = "HTML - Bar Charts" case 1: @@ -81,17 +81,17 @@ class DocumentsTableViewController: UITableViewController { func getDocumentCharts() -> [OCKDocumentElement] { - let bar1 = OCKBarSeries.init(title: "Title 1", values: [6,5], valueLabels: ["6","5"], tintColor: UIColor.brownColor()) - let bar2 = OCKBarSeries.init(title: "Title 2", values: [5,10], valueLabels: ["5","10"], tintColor: UIColor.blackColor()) - let bar3 = OCKBarSeries.init(title: "Title 3", values: [4,10], valueLabels: ["4","10"], tintColor: UIColor.blueColor()) - let bar4 = OCKBarSeries.init(title: "Title 4", values: [15,4], valueLabels: ["15","4"], tintColor: UIColor.grayColor()) - let bar5 = OCKBarSeries.init(title: "Title 7", values: [-20,-8], valueLabels: ["-20","-8"], tintColor: UIColor.cyanColor()) + let bar1 = OCKBarSeries.init(title: "Title 1", values: [6,5], valueLabels: ["6","5"], tintColor: UIColor.brown) + let bar2 = OCKBarSeries.init(title: "Title 2", values: [5,10], valueLabels: ["5","10"], tintColor: UIColor.black) + let bar3 = OCKBarSeries.init(title: "Title 3", values: [4,10], valueLabels: ["4","10"], tintColor: UIColor.blue) + let bar4 = OCKBarSeries.init(title: "Title 4", values: [15,4], valueLabels: ["15","4"], tintColor: UIColor.gray) + let bar5 = OCKBarSeries.init(title: "Title 7", values: [-20,-8], valueLabels: ["-20","-8"], tintColor: UIColor.cyan) - let chart1 = OCKBarChart.init(title: "Chart #1", text: "Chart #1 Description", tintColor: UIColor.grayColor(), axisTitles: ["Axis #1","Axis #2"], axisSubtitles: ["Subtitle #1","Subtitle #2"], dataSeries: [bar1, bar2, bar3, bar4, bar5]) + let chart1 = OCKBarChart.init(title: "Chart #1", text: "Chart #1 Description", tintColor: UIColor.gray, axisTitles: ["Axis #1","Axis #2"], axisSubtitles: ["Subtitle #1","Subtitle #2"], dataSeries: [bar1, bar2, bar3, bar4, bar5]) - let series1 = OCKBarSeries.init(title: "Series #1", values: [20,24,60,40,50,60], valueLabels: ["20","24","60","40","50","60"], tintColor: UIColor.darkGrayColor()) - let series2 = OCKBarSeries.init(title: "Series #2", values: [25,15,35,16,60,20], valueLabels: ["25","15","35","16","60","20"], tintColor: UIColor.orangeColor()) - let chart2 = OCKBarChart.init(title: "Chart #2", text: "Chart #2 Description", tintColor: UIColor.grayColor(), axisTitles: ["ABC","DEF","GHI","JKL","MNO"], axisSubtitles: ["123","456","789","012"],dataSeries: [series1, series2]) + let series1 = OCKBarSeries.init(title: "Series #1", values: [20,24,60,40,50,60], valueLabels: ["20","24","60","40","50","60"], tintColor: UIColor.darkGray) + let series2 = OCKBarSeries.init(title: "Series #2", values: [25,15,35,16,60,20], valueLabels: ["25","15","35","16","60","20"], tintColor: UIColor.orange) + let chart2 = OCKBarChart.init(title: "Chart #2", text: "Chart #2 Description", tintColor: UIColor.gray, axisTitles: ["ABC","DEF","GHI","JKL","MNO"], axisSubtitles: ["123","456","789","012"],dataSeries: [series1, series2]) return [OCKDocumentElementChart.init(chart: chart1),OCKDocumentElementChart.init(chart: chart2)] } @@ -142,22 +142,22 @@ class DocumentsTableViewController: UITableViewController { } - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let document = OCKDocument.init(title: "Here is a Title for the Document. \n This is a new line", elements: nil) document.pageHeader = "This Page Header should appear on the top of every single page" - if indexPath.row % 6 == 0 { // Rows 0 and 6 + if (indexPath as NSIndexPath).row % 6 == 0 { // Rows 0 and 6 document.elements = getDocumentCharts() - } else if indexPath.row % 6 == 1 { // Rows 1 and 7 + } else if (indexPath as NSIndexPath).row % 6 == 1 { // Rows 1 and 7 document.elements = getDocumentTables() - } else if indexPath.row % 6 == 2 { // Rows 2 and 8 + } else if (indexPath as NSIndexPath).row % 6 == 2 { // Rows 2 and 8 document.elements = getDocumentSubtitles() - } else if indexPath.row % 6 == 3 { // Rows 3 and 9 + } else if (indexPath as NSIndexPath).row % 6 == 3 { // Rows 3 and 9 document.elements = getDocumentImages() - } else if indexPath.row % 6 == 4 { // Rows 4 and 10 + } else if (indexPath as NSIndexPath).row % 6 == 4 { // Rows 4 and 10 document.elements = getDocumentParagraphs() - } else if indexPath.row % 6 == 5 { // Rows 5 and 11 + } else if (indexPath as NSIndexPath).row % 6 == 5 { // Rows 5 and 11 let chartsAndTables = getDocumentCharts() + getDocumentTables() let paragraphsAndImages = getDocumentParagraphs() + getDocumentImages() let subtitles = getDocumentSubtitles() @@ -165,26 +165,26 @@ class DocumentsTableViewController: UITableViewController { } let webViewController = UIViewController.init() - webViewController.view.backgroundColor = UIColor.whiteColor() + webViewController.view.backgroundColor = UIColor.white let webView = UIWebView.init() webView.translatesAutoresizingMaskIntoConstraints = false webViewController.view.addSubview(webView) - webView.topAnchor.constraintEqualToAnchor(webViewController.view.topAnchor, constant: 30).active = true - webView.bottomAnchor.constraintEqualToAnchor(webViewController.view.bottomAnchor).active = true - webView.leftAnchor.constraintEqualToAnchor(webViewController.view.leftAnchor).active = true - webView.rightAnchor.constraintEqualToAnchor(webViewController.view.rightAnchor).active = true + webView.topAnchor.constraint(equalTo: webViewController.view.topAnchor, constant: 30).isActive = true + webView.bottomAnchor.constraint(equalTo: webViewController.view.bottomAnchor).isActive = true + webView.leftAnchor.constraint(equalTo: webViewController.view.leftAnchor).isActive = true + webView.rightAnchor.constraint(equalTo: webViewController.view.rightAnchor).isActive = true - if indexPath.row >= 6 { + if (indexPath as NSIndexPath).row >= 6 { // PDFs - document.createPDFDataWithCompletion { (data, error) in - dispatch_async(dispatch_get_main_queue(),{ - webView.loadData(data, MIMEType: "application/pdf", textEncodingName: "", baseURL: NSURL()) + document.createPDFData { (data, error) in + DispatchQueue.main.async(execute: { + webView.load(data, mimeType: "application/pdf", textEncodingName: "", baseURL: URL(string: "")!) self.navigationController?.pushViewController(webViewController, animated: true) }) } } else { // HTMLs - webView.loadHTMLString(document.HTMLContent, baseURL: nil) + webView.loadHTMLString(document.htmlContent, baseURL: nil) self.navigationController?.pushViewController(webViewController, animated: true) } diff --git a/testing/OCKTest/OCKTest/InsightsTableViewController.swift b/testing/OCKTest/OCKTest/InsightsTableViewController.swift index 424910c79..b9dc41f6b 100644 --- a/testing/OCKTest/OCKTest/InsightsTableViewController.swift +++ b/testing/OCKTest/OCKTest/InsightsTableViewController.swift @@ -34,18 +34,18 @@ import CareKit class InsightsTableViewController: UITableViewController { - override func numberOfSectionsInTableView(tableView: UITableView) -> Int { + override func numberOfSections(in tableView: UITableView) -> Int { return 1 } - override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 7 } - override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if let cell = tableView.dequeueReusableCellWithIdentifier("cell") { - switch indexPath.row { + if let cell = tableView.dequeueReusableCell(withIdentifier: "cell") { + switch (indexPath as NSIndexPath).row { case 0: cell.textLabel?.text = "Many Bar Charts" case 1: @@ -70,120 +70,120 @@ class InsightsTableViewController: UITableViewController { } - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.row == 0 { + if (indexPath as NSIndexPath).row == 0 { // Many Charts - let chart1Series1 = OCKBarSeries.init(title: "Chart #1 Series #1", values: [20,04,60,40], valueLabels: ["20","04","60","40"], tintColor: UIColor.cyanColor()) - let chart1Series2 = OCKBarSeries.init(title: "Chart #1 Series #2", values: [5,15,35,16], valueLabels: ["5","15","35","16"], tintColor: UIColor.magentaColor()) - let chart1 = OCKBarChart.init(title: "Chart #1", text: "Chart #1 Description", tintColor: UIColor.grayColor(), axisTitles: ["ABC","DEF","GHI","JKL"], axisSubtitles: ["123","456","789","012"], dataSeries: [chart1Series1, chart1Series2]) + let chart1Series1 = OCKBarSeries.init(title: "Chart #1 Series #1", values: [20,04,60,40], valueLabels: ["20","04","60","40"], tintColor: UIColor.cyan) + let chart1Series2 = OCKBarSeries.init(title: "Chart #1 Series #2", values: [5,15,35,16], valueLabels: ["5","15","35","16"], tintColor: UIColor.magenta) + let chart1 = OCKBarChart.init(title: "Chart #1", text: "Chart #1 Description", tintColor: UIColor.gray, axisTitles: ["ABC","DEF","GHI","JKL"], axisSubtitles: ["123","456","789","012"], dataSeries: [chart1Series1, chart1Series2]) let chart2Series1 = OCKBarSeries.init(title: "", values: [2,4], valueLabels: ["2","4"], tintColor: nil) - let chart2Series2 = OCKBarSeries.init(title: "", values: [3,1], valueLabels: ["3","1"], tintColor: UIColor.brownColor()) - let chart2Series3 = OCKBarSeries.init(title: "", values: [1,4], valueLabels: ["1","4"], tintColor: UIColor.grayColor()) - let chart2Series4 = OCKBarSeries.init(title: "", values: [9,0], valueLabels: ["9","0"], tintColor: UIColor.blackColor()) + let chart2Series2 = OCKBarSeries.init(title: "", values: [3,1], valueLabels: ["3","1"], tintColor: UIColor.brown) + let chart2Series3 = OCKBarSeries.init(title: "", values: [1,4], valueLabels: ["1","4"], tintColor: UIColor.gray) + let chart2Series4 = OCKBarSeries.init(title: "", values: [9,0], valueLabels: ["9","0"], tintColor: UIColor.black) let chart2 = OCKBarChart.init(title: "Chart #2", text: "Chart #2 has no bar series titles and no subtitles", tintColor: nil , axisTitles: ["X","Y"], axisSubtitles: nil, dataSeries: [chart2Series1,chart2Series2, chart2Series3, chart2Series4]) - let chart3Series1 = OCKBarSeries.init(title: "No text/title", values: [1000,2000,6000,4000], valueLabels: ["1000","2000","6000","4000"], tintColor: UIColor.purpleColor()) - let chart3Series2 = OCKBarSeries.init(title: "No Axes", values: [1500,1500,1500,1500], valueLabels: ["1500","1500","1500","1500"], tintColor: UIColor.orangeColor()) - let chart3 = OCKBarChart.init(title: nil, text: nil, tintColor: UIColor.clearColor(), axisTitles: nil, axisSubtitles: nil, dataSeries: [chart3Series1, chart3Series2]) + let chart3Series1 = OCKBarSeries.init(title: "No text/title", values: [1000,2000,6000,4000], valueLabels: ["1000","2000","6000","4000"], tintColor: UIColor.purple) + let chart3Series2 = OCKBarSeries.init(title: "No Axes", values: [1500,1500,1500,1500], valueLabels: ["1500","1500","1500","1500"], tintColor: UIColor.orange) + let chart3 = OCKBarChart.init(title: nil, text: nil, tintColor: UIColor.clear, axisTitles: nil, axisSubtitles: nil, dataSeries: [chart3Series1, chart3Series2]) - let chart4Series1 = OCKBarSeries.init(title: "Series #1", values: [1], valueLabels: ["1"], tintColor: UIColor.cyanColor()) - let chart4Series2 = OCKBarSeries.init(title: "Series #2", values: [2], valueLabels: ["2"], tintColor: UIColor.magentaColor()) - let chart4Series3 = OCKBarSeries.init(title: "Series #3", values: [3], valueLabels: ["3"], tintColor: UIColor.orangeColor()) + let chart4Series1 = OCKBarSeries.init(title: "Series #1", values: [1], valueLabels: ["1"], tintColor: UIColor.cyan) + let chart4Series2 = OCKBarSeries.init(title: "Series #2", values: [2], valueLabels: ["2"], tintColor: UIColor.magenta) + let chart4Series3 = OCKBarSeries.init(title: "Series #3", values: [3], valueLabels: ["3"], tintColor: UIColor.orange) let chart4Series4 = OCKBarSeries.init(title: "Series #4", values: [4], valueLabels: ["4"], tintColor: nil) - let chart4Series5 = OCKBarSeries.init(title: "Series #5", values: [5], valueLabels: ["5"], tintColor: UIColor.yellowColor()) - let chart4Series6 = OCKBarSeries.init(title: "Series #6", values: [6], valueLabels: ["6"], tintColor: UIColor.redColor()) - let chart4Series7 = OCKBarSeries.init(title: "Series #7", values: [7], valueLabels: ["7"], tintColor: UIColor.purpleColor()) - let chart4 = OCKBarChart.init(title: "Chart #4", text: "Chart #4 Description\n spans over two lines", tintColor: UIColor.cyanColor(), axisTitles: ["A"], axisSubtitles: ["a"], dataSeries: [chart4Series1, chart4Series2, chart4Series3, chart4Series4, chart4Series5, chart4Series6, chart4Series7]) + let chart4Series5 = OCKBarSeries.init(title: "Series #5", values: [5], valueLabels: ["5"], tintColor: UIColor.yellow) + let chart4Series6 = OCKBarSeries.init(title: "Series #6", values: [6], valueLabels: ["6"], tintColor: UIColor.red) + let chart4Series7 = OCKBarSeries.init(title: "Series #7", values: [7], valueLabels: ["7"], tintColor: UIColor.purple) + let chart4 = OCKBarChart.init(title: "Chart #4", text: "Chart #4 Description\n spans over two lines", tintColor: UIColor.cyan, axisTitles: ["A"], axisSubtitles: ["a"], dataSeries: [chart4Series1, chart4Series2, chart4Series3, chart4Series4, chart4Series5, chart4Series6, chart4Series7]) - let chart5Series1 = OCKBarSeries.init(title: "Zero", values: [0], valueLabels: ["0"], tintColor: UIColor.redColor()) - let chart5Series2 = OCKBarSeries.init(title: "Zero", values: [0], valueLabels: ["0"], tintColor: UIColor.greenColor()) - let chart5 = OCKBarChart.init(title: "Chart #5", text: "Chart #5 Description\n spans over two lines", tintColor: UIColor.greenColor(), axisTitles: ["A","B"], axisSubtitles: ["abcdefgh","pqrstuvwxyz"], dataSeries: [chart5Series1, chart5Series2]) + let chart5Series1 = OCKBarSeries.init(title: "Zero", values: [0], valueLabels: ["0"], tintColor: UIColor.red) + let chart5Series2 = OCKBarSeries.init(title: "Zero", values: [0], valueLabels: ["0"], tintColor: UIColor.green) + let chart5 = OCKBarChart.init(title: "Chart #5", text: "Chart #5 Description\n spans over two lines", tintColor: UIColor.green, axisTitles: ["A","B"], axisSubtitles: ["abcdefgh","pqrstuvwxyz"], dataSeries: [chart5Series1, chart5Series2]) let insightsDashboardViewController = OCKInsightsViewController.init(insightItems: [chart1, chart2, chart3, chart4, chart5], headerTitle: "Insights Dashboard\nThis line should be hidden", headerSubtitle: "Many Bar Charts Here\nSubtitle can have two lines\nBut not three") self.navigationController?.pushViewController(insightsDashboardViewController, animated: true) - } else if indexPath.row == 1 { + } else if (indexPath as NSIndexPath).row == 1 { // Many Series in a Chart - let chart1Series1 = OCKBarSeries.init(title: "Chart #1 Series #1", values: [1,5], valueLabels: ["1","5"], tintColor: UIColor.brownColor()) - let chart1Series2 = OCKBarSeries.init(title: "Chart #1 Series #2", values: [5,10], valueLabels: ["5","10"], tintColor: UIColor.blackColor()) + let chart1Series1 = OCKBarSeries.init(title: "Chart #1 Series #1", values: [1,5], valueLabels: ["1","5"], tintColor: UIColor.brown) + let chart1Series2 = OCKBarSeries.init(title: "Chart #1 Series #2", values: [5,10], valueLabels: ["5","10"], tintColor: UIColor.black) let chart1Series3 = OCKBarSeries.init(title: "Chart #1 Series #3", values: [0.4,00.10], valueLabels: ["0.4","00.10"], tintColor: nil) - let chart1Series4 = OCKBarSeries.init(title: "Chart #1 Series #4", values: [15,2], valueLabels: ["15","2"], tintColor: UIColor.grayColor()) - let chart1Series5 = OCKBarSeries.init(title: "Chart #1 Series #5", values: [3,7], valueLabels: ["3","7"], tintColor: UIColor.greenColor()) + let chart1Series4 = OCKBarSeries.init(title: "Chart #1 Series #4", values: [15,2], valueLabels: ["15","2"], tintColor: UIColor.gray) + let chart1Series5 = OCKBarSeries.init(title: "Chart #1 Series #5", values: [3,7], valueLabels: ["3","7"], tintColor: UIColor.green) let chart1Series6 = OCKBarSeries.init(title: "Chart #1 Series #6", values: [20.0000,35.0000], valueLabels: ["Long Label: 20.0000","Another Long Label: 35.0000"], tintColor: nil) - let chart1Series7 = OCKBarSeries.init(title: "Chart #1 Series #7", values: [25,8], valueLabels: ["25","8"], tintColor: UIColor.cyanColor()) - let chart1Series8 = OCKBarSeries.init(title: "Chart #1 Series #8", values: [0,0], valueLabels: ["0","0"], tintColor: UIColor.blackColor()) + let chart1Series7 = OCKBarSeries.init(title: "Chart #1 Series #7", values: [25,8], valueLabels: ["25","8"], tintColor: UIColor.cyan) + let chart1Series8 = OCKBarSeries.init(title: "Chart #1 Series #8", values: [0,0], valueLabels: ["0","0"], tintColor: UIColor.black) let chart1Series9 = OCKBarSeries.init(title: "Negative Values", values: [-30,-40], valueLabels: ["-30","-40"], tintColor: nil) - let chart1 = OCKBarChart.init(title: "Chart #1", text: "Chart #1 Description", tintColor: UIColor.grayColor(), axisTitles: ["Title #1","Title #2"], axisSubtitles: ["Subtitle #1","Subtitle #2"], dataSeries: [chart1Series1, chart1Series2, chart1Series3, chart1Series4, chart1Series5, chart1Series6, chart1Series7, chart1Series8, chart1Series9]) + let chart1 = OCKBarChart.init(title: "Chart #1", text: "Chart #1 Description", tintColor: UIColor.gray, axisTitles: ["Title #1","Title #2"], axisSubtitles: ["Subtitle #1","Subtitle #2"], dataSeries: [chart1Series1, chart1Series2, chart1Series3, chart1Series4, chart1Series5, chart1Series6, chart1Series7, chart1Series8, chart1Series9]) let insightsDashboardViewController = OCKInsightsViewController.init(insightItems: [chart1]) self.navigationController?.pushViewController(insightsDashboardViewController, animated: true) - } else if indexPath.row == 2 { + } else if (indexPath as NSIndexPath).row == 2 { // Many Axes in a Chart - let barSeries1 = OCKBarSeries.init(title: "Me", values: [90000,98000,101000,80000,75000,100000,100100,120000,110000,115000,120000,125000,90000,98000,101000], valueLabels: ["90K","98K","101K","80K","75K","100K","100K","120K","110K","115K","120K","125K","90K","98K","101K"], tintColor: UIColor.purpleColor()) - let barSeries2 = OCKBarSeries.init(title: "US Average", values: [80000,90000,100000,120000,120000,130000,150000,120000,130000,135000,143000,145000], valueLabels: ["80K","90K","100K","120K","120K","130K","150K","120K","130K","135K","143K","145K"], tintColor: UIColor.brownColor()) + let barSeries1 = OCKBarSeries.init(title: "Me", values: [90000,98000,101000,80000,75000,100000,100100,120000,110000,115000,120000,125000,90000,98000,101000], valueLabels: ["90K","98K","101K","80K","75K","100K","100K","120K","110K","115K","120K","125K","90K","98K","101K"], tintColor: UIColor.purple) + let barSeries2 = OCKBarSeries.init(title: "US Average", values: [80000,90000,100000,120000,120000,130000,150000,120000,130000,135000,143000,145000], valueLabels: ["80K","90K","100K","120K","120K","130K","150K","120K","130K","135K","143K","145K"], tintColor: UIColor.brown) let barSeries3 = OCKBarSeries.init(title: "World Average", values: [120000,110000,130000,150000,120000,130000,135000,143000,145000,120000,130000,135000,143000,145000, 120000,130000,135000,143000,145000], valueLabels: ["120K","110K","130K","150K","120K","130K","135K","143K","145K","120K","130K","135K","143K","145K","120K","130K","135K","143K","145K"], tintColor: nil) - let barSeries4 = OCKBarSeries.init(title: "Canada Average", values: [80000,90000,100000,120000,130000,135000,143000,145000,120000,120000,130000,150000,80000,90000,100000,120000,130000,135000,145000,120000,120000,130000,150000], valueLabels: ["80K","90K","100K","120K","130K","135K","143K","145K","120K","120K","130K","150K","80K","90K","100K","120K","130K","135K","145K","120K","120K","130K","150K"], tintColor: UIColor.yellowColor()) - let chart1 = OCKBarChart.init(title: "Walking", text: "Step Count", tintColor: UIColor.grayColor(), axisTitles: ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","Jan'17","Feb'17","Mar'17","Apr'17","May'17","Jun'17","Jul'17","Aug'17","Sep'17","Oct'17","Nov'17","Dec'17"], axisSubtitles: nil, dataSeries: [barSeries1, barSeries2,barSeries3,barSeries4]) + let barSeries4 = OCKBarSeries.init(title: "Canada Average", values: [80000,90000,100000,120000,130000,135000,143000,145000,120000,120000,130000,150000,80000,90000,100000,120000,130000,135000,145000,120000,120000,130000,150000], valueLabels: ["80K","90K","100K","120K","130K","135K","143K","145K","120K","120K","130K","150K","80K","90K","100K","120K","130K","135K","145K","120K","120K","130K","150K"], tintColor: UIColor.yellow) + let chart1 = OCKBarChart.init(title: "Walking", text: "Step Count", tintColor: UIColor.gray, axisTitles: ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","Jan'17","Feb'17","Mar'17","Apr'17","May'17","Jun'17","Jul'17","Aug'17","Sep'17","Oct'17","Nov'17","Dec'17"], axisSubtitles: nil, dataSeries: [barSeries1, barSeries2,barSeries3,barSeries4]) let insightsDashboardViewController = OCKInsightsViewController.init(insightItems: [chart1]) insightsDashboardViewController.headerSubtitle = "This is a subtitle without a title" self.navigationController?.pushViewController(insightsDashboardViewController, animated: true) - } else if indexPath.row == 3 { + } else if (indexPath as NSIndexPath).row == 3 { // Messages - let messageItem1 = OCKMessageItem.init(title: "Alert", text: "This is an alert", tintColor: nil, messageType: OCKMessageItemType.Alert) - let messageItem2 = OCKMessageItem.init(title: "Tip", text: "This is a helpful tip", tintColor: nil, messageType: OCKMessageItemType.Tip) - let messageItem3 = OCKMessageItem.init(title: nil, text: nil, tintColor: nil, messageType: OCKMessageItemType.Alert) - let messageItem4 = OCKMessageItem.init(title: nil, text: nil, tintColor: nil, messageType: OCKMessageItemType.Tip) - let messageItem5 = OCKMessageItem.init(title: "Red Alert", text: "This is a red alert", tintColor: UIColor.redColor(), messageType: OCKMessageItemType.Alert) - let messageItem6 = OCKMessageItem.init(title: "Green Tip", text: "This is a green tip", tintColor: UIColor.greenColor(), messageType: OCKMessageItemType.Tip) - let messageItem7 = OCKMessageItem.init(title: "This is an alert with a very long title", text: LoremIpsum, tintColor: UIColor.init(hue: 0.4, saturation: 0.5, brightness: 0.3, alpha: 1), messageType: OCKMessageItemType.Alert) - let messageItem8 = OCKMessageItem.init(title: "This is a tip with an even longer title than the alert", text: "The text is long but not long enough. Blah Blah", tintColor: UIColor.init(red: 2, green: 0.4, blue: 0, alpha: 1), messageType: OCKMessageItemType.Tip) + let messageItem1 = OCKMessageItem.init(title: "Alert", text: "This is an alert", tintColor: nil, messageType: OCKMessageItemType.alert) + let messageItem2 = OCKMessageItem.init(title: "Tip", text: "This is a helpful tip", tintColor: nil, messageType: OCKMessageItemType.tip) + let messageItem3 = OCKMessageItem.init(title: nil, text: nil, tintColor: nil, messageType: OCKMessageItemType.alert) + let messageItem4 = OCKMessageItem.init(title: nil, text: nil, tintColor: nil, messageType: OCKMessageItemType.tip) + let messageItem5 = OCKMessageItem.init(title: "Red Alert", text: "This is a red alert", tintColor: UIColor.red, messageType: OCKMessageItemType.alert) + let messageItem6 = OCKMessageItem.init(title: "Green Tip", text: "This is a green tip", tintColor: UIColor.green, messageType: OCKMessageItemType.tip) + let messageItem7 = OCKMessageItem.init(title: "This is an alert with a very long title", text: LoremIpsum, tintColor: UIColor.init(hue: 0.4, saturation: 0.5, brightness: 0.3, alpha: 1), messageType: OCKMessageItemType.alert) + let messageItem8 = OCKMessageItem.init(title: "This is a tip with an even longer title than the alert", text: "The text is long but not long enough. Blah Blah", tintColor: UIColor.init(red: 2, green: 0.4, blue: 0, alpha: 1), messageType: OCKMessageItemType.tip) let insightsDashboardViewController = OCKInsightsViewController.init(insightItems: [messageItem1, messageItem2, messageItem3, messageItem4, messageItem5, messageItem6, messageItem7, messageItem8]) self.navigationController?.pushViewController(insightsDashboardViewController, animated: true) - } else if indexPath.row == 4 { + } else if (indexPath as NSIndexPath).row == 4 { // Messages + Charts - let messageItem1 = OCKMessageItem.init(title: "Alert", text: "This is an alert", tintColor: nil, messageType: OCKMessageItemType.Alert) - let messageItem2 = OCKMessageItem.init(title: "Tip", text: "This is a tip", tintColor: nil, messageType: OCKMessageItemType.Tip) - let series1 = OCKBarSeries.init(title: "Chart #1 Series #1", values: [20,04,60,40,50,60], valueLabels: ["20","04","60","40","50","60"], tintColor: UIColor.blackColor()) - let series2 = OCKBarSeries.init(title: "Chart #1 Series #2", values: [5,15,35,16,100,20], valueLabels: ["5","15","35","16","100","20"], tintColor: UIColor.orangeColor()) - let chart1 = OCKBarChart.init(title: "Chart #1", text: "Chart #1 Description", tintColor: UIColor.grayColor(), axisTitles: ["ABC","DEF","GHI","JKL","MNO"], axisSubtitles: ["123","456","789","012"], dataSeries: [series1, series2]) - let messageItem3 = OCKMessageItem.init(title: "Another Alert", text: nil, tintColor: UIColor.orangeColor(), messageType: OCKMessageItemType.Alert) - let messageItem4 = OCKMessageItem.init(title: "Another Tip", text: nil, tintColor: UIColor.greenColor(), messageType: OCKMessageItemType.Tip) + let messageItem1 = OCKMessageItem.init(title: "Alert", text: "This is an alert", tintColor: nil, messageType: OCKMessageItemType.alert) + let messageItem2 = OCKMessageItem.init(title: "Tip", text: "This is a tip", tintColor: nil, messageType: OCKMessageItemType.tip) + let series1 = OCKBarSeries.init(title: "Chart #1 Series #1", values: [20,04,60,40,50,60], valueLabels: ["20","04","60","40","50","60"], tintColor: UIColor.black) + let series2 = OCKBarSeries.init(title: "Chart #1 Series #2", values: [5,15,35,16,100,20], valueLabels: ["5","15","35","16","100","20"], tintColor: UIColor.orange) + let chart1 = OCKBarChart.init(title: "Chart #1", text: "Chart #1 Description", tintColor: UIColor.gray, axisTitles: ["ABC","DEF","GHI","JKL","MNO"], axisSubtitles: ["123","456","789","012"], dataSeries: [series1, series2]) + let messageItem3 = OCKMessageItem.init(title: "Another Alert", text: nil, tintColor: UIColor.orange, messageType: OCKMessageItemType.alert) + let messageItem4 = OCKMessageItem.init(title: "Another Tip", text: nil, tintColor: UIColor.green, messageType: OCKMessageItemType.tip) let insightsDashboardViewController = OCKInsightsViewController.init(insightItems: [messageItem1, messageItem2,chart1, messageItem3, messageItem4]) insightsDashboardViewController.headerTitle = "Dashboard with Messages and Bar Charts" insightsDashboardViewController.showEdgeIndicators = true self.navigationController?.pushViewController(insightsDashboardViewController, animated: true) - } else if indexPath.row == 5 { + } else if (indexPath as NSIndexPath).row == 5 { // Custom Charts let chart1 = CustomChart.init(chartSize: 300, bubbleSize: 100) - chart1.tintColor = UIColor.purpleColor() + chart1.tintColor = UIColor.purple chart1.title = "1. Custom Chart" let chart2 = CustomChart.init(chartSize: 150, bubbleSize: 50) - chart2.tintColor = UIColor.blueColor() + chart2.tintColor = UIColor.blue chart2.title = "2. Custom Chart" let chart3 = CustomChart.init(chartSize: 250, bubbleSize: 20) - chart3.tintColor = UIColor.orangeColor() + chart3.tintColor = UIColor.orange chart3.title = "3. Custom Chart" let insightsDashboardViewController = OCKInsightsViewController.init(insightItems: [chart1, chart2, chart3]) @@ -191,30 +191,30 @@ class InsightsTableViewController: UITableViewController { insightsDashboardViewController.showEdgeIndicators = true self.navigationController?.pushViewController(insightsDashboardViewController, animated: true) - } else if indexPath.row == 6 { + } else if (indexPath as NSIndexPath).row == 6 { // Custom Scales - let chart1Series1 = OCKBarSeries.init(title: "👍", values: [0,20], valueLabels: ["0","20"], tintColor: UIColor.cyanColor()) - let chart1Series2 = OCKBarSeries.init(title: "👫", values: [5,15], valueLabels: ["5","15"], tintColor: UIColor.magentaColor()) - let chart1 = OCKBarChart.init(title: "Only Min Scale", text: "Minimum Scale = -10", tintColor: UIColor.cyanColor(), axisTitles: ["α","β"], axisSubtitles: ["😀","🤗"], dataSeries: [chart1Series1, chart1Series2], minimumScaleRangeValue: -10, maximumScaleRangeValue: nil) + let chart1Series1 = OCKBarSeries.init(title: "👍", values: [0,20], valueLabels: ["0","20"], tintColor: UIColor.cyan) + let chart1Series2 = OCKBarSeries.init(title: "👫", values: [5,15], valueLabels: ["5","15"], tintColor: UIColor.magenta) + let chart1 = OCKBarChart.init(title: "Only Min Scale", text: "Minimum Scale = -10", tintColor: UIColor.cyan, axisTitles: ["α","β"], axisSubtitles: ["😀","🤗"], dataSeries: [chart1Series1, chart1Series2], minimumScaleRangeValue: -10, maximumScaleRangeValue: nil) let chart2Series1 = OCKBarSeries.init(title: "比", values: [20,50], valueLabels: ["20","50"], tintColor: nil) - let chart2Series2 = OCKBarSeries.init(title: "诶", values: [-10,2], valueLabels: ["-10","2"], tintColor: UIColor.purpleColor()) - let chart2 = OCKBarChart.init(title: "Only Max Scale", text: "Maximum Scale = 100", tintColor: UIColor.clearColor(), axisTitles: ["艾尺","艾"], axisSubtitles: ["艾丝","提"], dataSeries: [chart2Series1, chart2Series2], minimumScaleRangeValue: nil, maximumScaleRangeValue: 100) + let chart2Series2 = OCKBarSeries.init(title: "诶", values: [-10,2], valueLabels: ["-10","2"], tintColor: UIColor.purple) + let chart2 = OCKBarChart.init(title: "Only Max Scale", text: "Maximum Scale = 100", tintColor: UIColor.clear, axisTitles: ["艾尺","艾"], axisSubtitles: ["艾丝","提"], dataSeries: [chart2Series1, chart2Series2], minimumScaleRangeValue: nil, maximumScaleRangeValue: 100) - let chart3Series1 = OCKBarSeries.init(title: "غ", values: [1000.2,1002], valueLabels: ["1000.2","1002"], tintColor: UIColor.brownColor()) - let chart3Series2 = OCKBarSeries.init(title: "ظ", values: [1003,1005], valueLabels: ["1003","1005"], tintColor: UIColor.redColor()) - let chart3 = OCKBarChart.init(title: "Min & Max Scale", text: "Min = 1000, Max = 1005", tintColor: UIColor.orangeColor(), axisTitles: ["ت","ش"], axisSubtitles: ["ض","ذ"], dataSeries: [chart3Series1, chart3Series2], minimumScaleRangeValue: 1000, maximumScaleRangeValue: 1005) + let chart3Series1 = OCKBarSeries.init(title: "غ", values: [1000.2,1002], valueLabels: ["1000.2","1002"], tintColor: UIColor.brown) + let chart3Series2 = OCKBarSeries.init(title: "ظ", values: [1003,1005], valueLabels: ["1003","1005"], tintColor: UIColor.red) + let chart3 = OCKBarChart.init(title: "Min & Max Scale", text: "Min = 1000, Max = 1005", tintColor: UIColor.orange, axisTitles: ["ت","ش"], axisSubtitles: ["ض","ذ"], dataSeries: [chart3Series1, chart3Series2], minimumScaleRangeValue: 1000, maximumScaleRangeValue: 1005) - let chart4Series1 = OCKBarSeries.init(title: "ц", values: [50, 100, 150, 200, 250 ], valueLabels: ["50","100","150","200","250"], tintColor: UIColor.darkGrayColor()) - let chart4 = OCKBarChart.init(title: "Min > Max", text: "Min = 200, Max = 100", tintColor: UIColor.darkGrayColor(), axisTitles: ["ѯ","ѱ","ѣ","ѭ","ѩ"], axisSubtitles: nil, dataSeries: [chart4Series1], minimumScaleRangeValue: 200, maximumScaleRangeValue: 100) + let chart4Series1 = OCKBarSeries.init(title: "ц", values: [50, 100, 150, 200, 250 ], valueLabels: ["50","100","150","200","250"], tintColor: UIColor.darkGray) + let chart4 = OCKBarChart.init(title: "Min > Max", text: "Min = 200, Max = 100", tintColor: UIColor.darkGray, axisTitles: ["ѯ","ѱ","ѣ","ѭ","ѩ"], axisSubtitles: nil, dataSeries: [chart4Series1], minimumScaleRangeValue: 200, maximumScaleRangeValue: 100) let chart5Series1 = OCKBarSeries.init(title: "अं", values: [-10000, -100000, -150000, -200000], valueLabels: ["-10000","-100000","-150000","-200000"], tintColor: nil) let chart5 = OCKBarChart.init(title: "Min & Max Negative", text: "Min = -200000, Max = -10000", tintColor: nil, axisTitles: ["क","ख","ग","घ"], axisSubtitles: nil, dataSeries: [chart5Series1], minimumScaleRangeValue: -200000, maximumScaleRangeValue: -10000) - let chart6Series1 = OCKBarSeries.init(title: "A", values: [NSNumber(longLong:Int64.min), NSNumber(longLong:Int64.max)], valueLabels: ["Int64.min","Int64.max"], tintColor: UIColor.greenColor()) - let chart6 = OCKBarChart.init(title: "Min & Max Int values", text: "Min = Int64.min, Max = Int64.max", tintColor: UIColor.greenColor(), axisTitles: nil, axisSubtitles: ["Min","Max"], dataSeries: [chart6Series1], minimumScaleRangeValue: NSNumber(longLong:Int64.min), maximumScaleRangeValue: NSNumber(longLong:Int64.max)) + let chart6Series1 = OCKBarSeries.init(title: "A", values: [NSNumber(value:Int64.min), NSNumber(value:Int64.max)], valueLabels: ["Int64.min","Int64.max"], tintColor: UIColor.green) + let chart6 = OCKBarChart.init(title: "Min & Max Int values", text: "Min = Int64.min, Max = Int64.max", tintColor: UIColor.green, axisTitles: nil, axisSubtitles: ["Min","Max"], dataSeries: [chart6Series1], minimumScaleRangeValue: NSNumber(value:Int64.min), maximumScaleRangeValue: NSNumber(value:Int64.max)) let insightsDashboardViewController = OCKInsightsViewController.init(insightItems: [chart1, chart2, chart3, chart4, chart5, chart6]) insightsDashboardViewController.headerTitle = "Minimum/Maximum Scales" diff --git a/testing/OCKTest/OCKTest/MainTableViewController.h b/testing/OCKTest/OCKTest/MainTableViewController.h new file mode 100644 index 000000000..a2bb8b71f --- /dev/null +++ b/testing/OCKTest/OCKTest/MainTableViewController.h @@ -0,0 +1,37 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +@interface MainTableViewController : UITableViewController + +@end diff --git a/testing/OCKTest/OCKTest/MainTableViewController.m b/testing/OCKTest/OCKTest/MainTableViewController.m new file mode 100644 index 000000000..ca35aa1cf --- /dev/null +++ b/testing/OCKTest/OCKTest/MainTableViewController.m @@ -0,0 +1,706 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "MainTableViewController.h" +#import "BarChartViewController.h" +#import "DocumentViewController.h" + + +#define DefineStringKey(x) static NSString *const x = @#x +#define UIColorFromRGB(rgbValue) [UIColor \ +colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ +green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \ +blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] + +#define RedColor() UIColorFromRGB(0xEF445B); +#define GreenColor() UIColorFromRGB(0x8DC63F); +#define BlueColor() UIColorFromRGB(0x3EA1EE); +#define PurpleColor() UIColorFromRGB(0x9B59B6); +#define PinkColor() UIColorFromRGB(0xF26D7D); +#define YellowColor() UIColorFromRGB(0xF1DF15); +#define OrangeColor() UIColorFromRGB(0xF89406); +#define GrayColor() UIColorFromRGB(0xBDC3C7); + +static const BOOL resetStoreOnLaunch = YES; + +typedef NS_ENUM(NSInteger, TestItem) { + TestItemInsights, + TestItemBarChartView, + TestItemCareCard, + TestItemCareCardCustom, + TestItemSymptomTracker, + TestItemConnectPage, + TestItemDocument, + TestItemCount +}; + + +@implementation MainTableViewController { + NSArray *_items; + NSArray *_interventions; + NSArray *_assessments; + NSArray *_contacts; + OCKCarePlanStore *_store; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + self.title = @"OCKTest"; + [self setUpCarePlanStore]; +} + +- (UIViewController *)viewControllerForTestItem:(TestItem)testItem { + UIViewController *viewController = nil; + switch (testItem) { + case TestItemInsights: + viewController = [self insightsViewController]; + break; + case TestItemBarChartView: + viewController = [BarChartViewController new]; + break; + case TestItemCareCard: + viewController = [self careCardViewController]; + break; + case TestItemSymptomTracker: + viewController = [self symptomTrackerViewController]; + break; + case TestItemCareCardCustom: + viewController = [self careCardViewControllerCustom]; + break; + case TestItemConnectPage: + viewController = [self connectViewController]; + break; + case TestItemDocument: + viewController = [DocumentViewController new]; + break; + default: + break; + } + return viewController; +} + + +#pragma mark - Care Plan Store + +- (NSString *)storeDirectoryPath { + NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *docPath = [searchPaths objectAtIndex:0]; + NSString *path = [docPath stringByAppendingPathComponent:@"carePlanStore"]; + [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil]; + return path; +} + +- (NSURL *)storeDirectoryURL { + return [NSURL fileURLWithPath:[self storeDirectoryPath]]; +} + +- (void)setUpCarePlanStore { + if (resetStoreOnLaunch) { + [[NSFileManager defaultManager] removeItemAtPath:[self storeDirectoryPath] error:nil]; + } + + _store = [[OCKCarePlanStore alloc] initWithPersistenceDirectoryURL:[self storeDirectoryURL]]; + + [self generateInterventions]; + for (OCKCarePlanActivity *intervention in _interventions) { + [_store addActivity:intervention completion:^(BOOL success, NSError * _Nonnull error) { + if (!success) { + NSLog(@"%@", error.localizedDescription); + } + }]; + } + + [self generateAssessments]; + for (OCKCarePlanActivity *assessment in _assessments) { + [_store addActivity:assessment completion:^(BOOL success, NSError * _Nonnull error) { + if (!success) { + NSLog(@"%@", error.localizedDescription); + } + }]; + } +} + + +#pragma mark - OCKInsightsViewController + +- (OCKInsightsViewController *)insightsViewController { + [self generateItems]; + + OCKInsightsViewController *insightsViewController = [[OCKInsightsViewController alloc] initWithInsightItems:_items]; + insightsViewController.headerTitle = @"Weekly Insights"; + insightsViewController.headerSubtitle = @"3/15 - 3/21"; + return insightsViewController; +} + +- (void)generateItems { + NSMutableArray *items = [NSMutableArray new]; + + NSArray *axisTitles = @[@"S", @"M", @"T", @"W", @"T", @"F", @"S"]; + NSArray *axisSubtitles = @[@"3/15", @"", @"", @"", @"", @"", @"3/21"]; + + { + UIColor *color = PinkColor(); + OCKMessageItem *item = [[OCKMessageItem alloc] initWithTitle:@"Medication Adherence" + text:@"Your Ibuprofen adherence was 90% last week which resulted in your targeted pain score of 4." + tintColor:color + messageType:OCKMessageItemTypeTip]; + [items addObject:item]; + } + + { + UIColor *color = BlueColor(); + UIColor *lightColor = [color colorWithAlphaComponent:0.5]; + + OCKBarSeries *series1 = [[OCKBarSeries alloc] initWithTitle:@"Pain" + values:@[@9, @8, @7, @7, @5, @4, @2] + valueLabels:@[@"9", @"8", @"7", @"7", @"5", @"4", @"2"] + tintColor:color]; + + OCKBarSeries *series2 = [[OCKBarSeries alloc] initWithTitle:@"Medication" + values:@[@3, @4, @5, @7, @8, @9, @9] + valueLabels:@[@"30%", @"40%", @"50%", @"70%", @"80%", @"90%", @"90%"] + tintColor:lightColor]; + + OCKBarChart *chart = [[OCKBarChart alloc] initWithTitle:@"Pain Scores" + text:@"with Medication" + tintColor:nil + axisTitles:axisTitles + axisSubtitles:axisSubtitles + dataSeries:@[series1, series2]]; + chart.tintColor = color; + [items addObject:chart]; + } + + { + UIColor *color = GreenColor(); + OCKMessageItem *item = [[OCKMessageItem alloc] initWithTitle:@"Pain Score Update" + text:@"Your pain score changed from 9 to 4 in the past week." + tintColor:color + messageType:OCKMessageItemTypeAlert]; + [items addObject:item]; + } + + { + UIColor *color = PurpleColor(); + UIColor *lightColor = [color colorWithAlphaComponent:0.5]; + + OCKBarSeries *series1 = [[OCKBarSeries alloc] initWithTitle:@"Range of Motion" + values:@[@1, @4, @5, @5, @7, @9, @10] + valueLabels:@[@"10\u00B0", @"40\u00B0", @"50\u00B0", @"50\u00B0", @"70\u00B0", @"90\u00B0", @"100\u00B0"] + tintColor:color]; + + OCKBarSeries *series2 = [[OCKBarSeries alloc] initWithTitle:@"Arm Stretches" + values:@[@8.5, @7, @5, @4, @3, @3, @2] + valueLabels:@[@"85%", @"75%", @"50%", @"54%", @"30%", @"30%", @"20%"] + tintColor:lightColor]; + + OCKBarChart *chart = [[OCKBarChart alloc] initWithTitle:@"Range of Motion" + text:@"with Arm Stretch Completion" + tintColor:color + axisTitles:axisTitles + axisSubtitles:axisSubtitles + dataSeries:@[series1, series2]]; + chart.tintColor = color; + [items addObject:chart]; + } + + _items = [items copy]; +} + + +#pragma mark - OCKCareCardViewController + +DefineStringKey(MedicationIntervention); +DefineStringKey(MoveIntervention); +DefineStringKey(DietIntervention); +DefineStringKey(BandageIntervention); + +DefineStringKey(MedicationChangeIntervention); +DefineStringKey(MoveChangeIntervention); +DefineStringKey(DietChangeIntervention); +DefineStringKey(BandageChangeIntervention); + +- (OCKCareCardViewController *)careCardViewControllerCustom { + OCKCareCardViewController *careCardViewController = [[OCKCareCardViewController alloc] initWithCarePlanStore:_store]; + careCardViewController.maskImage = [UIImage imageNamed:@"doctor"]; + careCardViewController.smallMaskImage = [UIImage imageNamed:@"doctor"]; + careCardViewController.maskImageTintColor = PurpleColor(); + return careCardViewController; +} + +- (OCKCareCardViewController *)careCardViewController { + OCKCareCardViewController *careCardViewController = [[OCKCareCardViewController alloc] initWithCarePlanStore:_store]; + careCardViewController.delegate = self; + return careCardViewController; +} + +- (void)generateInterventions { + NSMutableArray *interventions = [NSMutableArray new]; + + NSDateComponents *startDate = [[NSDateComponents alloc] initWithYear:2016 month:01 day:01]; + + { + OCKCareSchedule *schedule = [OCKCareSchedule weeklyScheduleWithStartDate:startDate occurrencesOnEachDay:@[@4,@10,@10,@12,@12,@0,@0]]; + + UIGraphicsBeginImageContext(self.view.frame.size); + [self.view.layer renderInContext:UIGraphicsGetCurrentContext()]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + NSData *data = UIImagePNGRepresentation(image); + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + NSString *path = [documentsDirectory stringByAppendingPathComponent:@"view.png"]; + [data writeToFile:path atomically:YES]; + + OCKCarePlanActivity *intervention = [OCKCarePlanActivity interventionWithIdentifier:MedicationIntervention + groupIdentifier:nil + title:@"Hydrocodone/Acetaminophen" + text:@"5mg/300mg" + tintColor:nil + instructions:@"Take twice daily with food. May cause drowsiness. It is not recommended to drive with this medication. For any severe side effects, please contact your physician." + imageURL:[NSURL fileURLWithPath:path] + schedule:schedule + userInfo:nil]; + + [interventions addObject:intervention]; + } + + { + OCKCareSchedule *schedule = [OCKCareSchedule weeklyScheduleWithStartDate:startDate occurrencesOnEachDay:@[@2,@2,@2,@2,@2,@0,@0]]; + UIColor *color = PurpleColor(); + + OCKCarePlanActivity *intervention = [OCKCarePlanActivity interventionWithIdentifier:MoveIntervention + groupIdentifier:nil + title:@"Stand and move a little" + text:@"For at least 2 minutes" + tintColor:color + instructions:nil + imageURL:nil + schedule:schedule + userInfo:nil]; + [interventions addObject:intervention]; + } + + { + OCKCareSchedule *schedule = [OCKCareSchedule weeklyScheduleWithStartDate:startDate occurrencesOnEachDay:@[@4,@4,@4,@4,@4,@0,@0]]; + UIColor *color = GreenColor(); + + OCKCarePlanActivity *intervention = [OCKCarePlanActivity interventionWithIdentifier:DietIntervention + groupIdentifier:nil + title:@"Diet" + text:@"Fluids only, every 6 hours" + tintColor:color + instructions:nil + imageURL:nil + schedule:schedule + userInfo:nil]; + [interventions addObject:intervention]; + } + + { + OCKCareSchedule *schedule = [OCKCareSchedule weeklyScheduleWithStartDate:startDate occurrencesOnEachDay:@[@1,@1,@1,@1,@1,@0,@0]]; + UIColor *color = PinkColor(); + + OCKCarePlanActivity *intervention = [OCKCarePlanActivity interventionWithIdentifier:BandageIntervention + groupIdentifier:nil + title:@"Keep bandage dry" + text:@"Do not change gauze" + tintColor:color + instructions:nil + imageURL:nil + schedule:schedule + userInfo:nil]; + [interventions addObject:intervention]; + } + + { + OCKCareSchedule *schedule = [OCKCareSchedule weeklyScheduleWithStartDate:startDate occurrencesOnEachDay:@[@0,@0,@0,@0,@0,@3,@3]]; + UIColor *color = BlueColor(); + + OCKCarePlanActivity *intervention = [OCKCarePlanActivity interventionWithIdentifier:MedicationChangeIntervention + groupIdentifier:nil + title:@"Ibuprofen" + text:@"400mg" + tintColor:color + instructions:nil + imageURL:nil + schedule:schedule + userInfo:nil]; + [interventions addObject:intervention]; + } + + { + OCKCareSchedule *schedule = [OCKCareSchedule weeklyScheduleWithStartDate:startDate occurrencesOnEachDay:@[@0,@0,@0,@0,@0,@2,@2]]; + UIColor *color = PurpleColor(); + + OCKCarePlanActivity *intervention = [OCKCarePlanActivity interventionWithIdentifier:MoveChangeIntervention + groupIdentifier:nil + title:@"Walk" + text:@"5 minutes" + tintColor:color + instructions:nil + imageURL:nil + schedule:schedule + userInfo:nil]; + [interventions addObject:intervention]; + } + + { + OCKCareSchedule *schedule = [OCKCareSchedule weeklyScheduleWithStartDate:startDate occurrencesOnEachDay:@[@0,@0,@0,@0,@0,@4,@4]]; + UIColor *color = GreenColor(); + + OCKCarePlanActivity *intervention = [OCKCarePlanActivity interventionWithIdentifier:DietIntervention + groupIdentifier:nil + title:@"Diet" + text:@"Eat soft solid foods every 6 hours" + tintColor:color + instructions:nil + imageURL:nil + schedule:schedule + userInfo:nil]; + [interventions addObject:intervention]; + } + + { + OCKCareSchedule *schedule = [OCKCareSchedule weeklyScheduleWithStartDate:startDate occurrencesOnEachDay:@[@0,@0,@0,@0,@0,@1,@1]]; + UIColor *color = PinkColor(); + + OCKCarePlanActivity *intervention = [OCKCarePlanActivity interventionWithIdentifier:BandageChangeIntervention + groupIdentifier:nil + title:@"Change bandage" + text:@"Use new gauze" + tintColor:color + instructions:nil + imageURL:nil + schedule:schedule + userInfo:nil]; + [interventions addObject:intervention]; + } + + _interventions = [interventions copy]; +} + +- (BOOL)careCardViewController:(OCKCareCardViewController *)viewController shouldHandleEventCompletionForActivity:(OCKCarePlanActivity *)interventionActivity { + BOOL shouldHandleEventCompletion = YES; + if ([interventionActivity.identifier isEqualToString:MoveIntervention]) { + shouldHandleEventCompletion = NO; + } + return shouldHandleEventCompletion; +} + +- (void)careCardViewController:(OCKCareCardViewController *)viewController didSelectButtonWithInterventionEvent:(OCKCarePlanEvent *)interventionEvent { + if ([interventionEvent.activity.identifier isEqualToString:MoveIntervention]) { + OCKCarePlanEventState state = (interventionEvent.state == OCKCarePlanEventStateCompleted) ? OCKCarePlanEventStateNotCompleted : OCKCarePlanEventStateCompleted; + + [viewController.store updateEvent:interventionEvent + withResult:nil + state:state + completion:^(BOOL success, OCKCarePlanEvent * _Nullable event, NSError * _Nullable error) { + NSAssert(success, error.localizedDescription); + }]; + } +} + + +#pragma mark - OCKSymptomTrackerViewController + +DefineStringKey(RangeOfMotionAssessment); +DefineStringKey(PainAssessment); +DefineStringKey(BleedingAssessment); +DefineStringKey(TemperatureAssessment); + +- (OCKSymptomTrackerViewController *)symptomTrackerViewController { + OCKSymptomTrackerViewController *symptomTrackerViewController = [[OCKSymptomTrackerViewController alloc] initWithCarePlanStore:_store]; + symptomTrackerViewController.delegate = self; + symptomTrackerViewController.progressRingTintColor = [UIColor greenColor]; + return symptomTrackerViewController; +} + +- (void)generateAssessments { + NSMutableArray *assessments = [NSMutableArray new]; + + NSDateComponents *startDate = [[NSDateComponents alloc] initWithYear:2016 month:01 day:01]; + + { + OCKCareSchedule *schedule = [OCKCareSchedule dailyScheduleWithStartDate:startDate occurrencesPerDay:1]; + + OCKCarePlanActivity *assessment = [OCKCarePlanActivity assessmentWithIdentifier:RangeOfMotionAssessment + groupIdentifier:nil + title:@"Range of Motion" + text:@"Arm movement" + tintColor:nil + resultResettable:NO + schedule:schedule + userInfo:nil]; + [assessments addObject:assessment]; + } + + { + OCKCareSchedule *schedule = [OCKCareSchedule dailyScheduleWithStartDate:startDate occurrencesPerDay:3]; + UIColor *color = BlueColor(); + + OCKCarePlanActivity *assessment = [OCKCarePlanActivity assessmentWithIdentifier:PainAssessment + groupIdentifier:nil + title:@"Pain jasdfj sadfj " + text:@"Scale assessment asdfkj sadfkj " + tintColor:color + resultResettable:NO + schedule:schedule + userInfo:nil]; + [assessments addObject:assessment]; + } + + { + OCKCareSchedule *schedule = [OCKCareSchedule dailyScheduleWithStartDate:startDate occurrencesPerDay:1]; + UIColor *color = GreenColor(); + + OCKCarePlanActivity *assessment = [OCKCarePlanActivity assessmentWithIdentifier:BleedingAssessment + groupIdentifier:nil + title:@"Bleeding" + text:@"Around wound" + tintColor:color + resultResettable:NO + schedule:schedule + userInfo:nil]; + [assessments addObject:assessment]; + } + + { + OCKCareSchedule *schedule = [OCKCareSchedule dailyScheduleWithStartDate:startDate occurrencesPerDay:1]; + UIColor *color = YellowColor(); + + OCKCarePlanActivity *assessment = [OCKCarePlanActivity assessmentWithIdentifier:TemperatureAssessment + groupIdentifier:nil + title:@"Temperature" + text:@"Oral" + tintColor:color + resultResettable:NO + schedule:schedule + userInfo:nil]; + [assessments addObject:assessment]; + } + + _assessments = [assessments copy]; +} + +- (void)symptomTrackerViewController:(OCKSymptomTrackerViewController *)viewController didSelectRowWithAssessmentEvent:(OCKCarePlanEvent *)assessmentEvent { + NSString *identifier = assessmentEvent.activity.identifier; + + if ([identifier isEqualToString:RangeOfMotionAssessment]) { + OCKCarePlanEventResult *result = [[OCKCarePlanEventResult alloc] initWithValueString:@"50" + unitString:@"degrees" + userInfo:nil]; + [_store updateEvent:assessmentEvent + withResult:result + state:OCKCarePlanEventStateCompleted + completion:^(BOOL success, OCKCarePlanEvent * _Nonnull event, NSError * _Nonnull error) { + NSAssert(success, error.localizedDescription); + }]; + } else if ([identifier isEqualToString:PainAssessment]) { + OCKCarePlanEventResult *result = [[OCKCarePlanEventResult alloc] initWithValueString:@"6 asdfkj lkdasf" + unitString:@"of 10" + userInfo:nil]; + [_store updateEvent:assessmentEvent + withResult:result + state:OCKCarePlanEventStateCompleted + completion:^(BOOL success, OCKCarePlanEvent * _Nonnull event, NSError * _Nonnull error) { + NSAssert(success, error.localizedDescription); + }]; + } else if ([identifier isEqualToString:BleedingAssessment]) { + OCKCarePlanEventResult *result = [[OCKCarePlanEventResult alloc] initWithValueString:@"2" + unitString:@"of 10" + userInfo:nil]; + [_store updateEvent:assessmentEvent + withResult:result + state:OCKCarePlanEventStateCompleted + completion:^(BOOL success, OCKCarePlanEvent * _Nonnull event, NSError * _Nonnull error) { + NSAssert(success, error.localizedDescription); + }]; + } else if ([identifier isEqualToString:TemperatureAssessment]) { + + HKHealthStore *hkstore = [HKHealthStore new]; + HKQuantityType *type = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature]; + + [hkstore requestAuthorizationToShareTypes:[NSSet setWithObject:type] + readTypes:[NSSet setWithObject:type] + completion:^(BOOL success, NSError * _Nullable error) { + + HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type + quantity:[HKQuantity quantityWithUnit:[HKUnit degreeFahrenheitUnit] doubleValue:99.1] + startDate:[NSDate date] + endDate:[NSDate date]]; + + [hkstore saveObject:sample withCompletion:^(BOOL success, NSError * _Nullable error) { + OCKCarePlanEventResult *result = [[OCKCarePlanEventResult alloc] initWithQuantitySample:sample + quantityStringFormatter:nil + unitStringKeys:@{[HKUnit degreeFahrenheitUnit]: @"\u00B0F", + [HKUnit degreeCelsiusUnit]: @"\u00B0C",} + userInfo:nil]; + [_store updateEvent:assessmentEvent + withResult:result + state:OCKCarePlanEventStateCompleted + completion:^(BOOL success, OCKCarePlanEvent * _Nonnull event, NSError * _Nonnull error) { + NSAssert(success, error.localizedDescription); + }]; + }]; + + }]; + } +} + + +#pragma mark - OCKConnectViewController + +- (OCKConnectViewController *)connectViewController { + [self generateContacts]; + + OCKConnectViewController *connectViewController = [[OCKConnectViewController alloc] initWithContacts:_contacts]; + connectViewController.delegate = self; + return connectViewController; +} + +- (void)generateContacts { + NSMutableArray *contacts = [NSMutableArray new]; + + { + UIColor *color = BlueColor(); + OCKContact *contact = [[OCKContact alloc] initWithContactType:OCKContactTypeCareTeam + name:@"Dr. Maria Ruiz" + relation:@"Physician" + tintColor:color + phoneNumber:[CNPhoneNumber phoneNumberWithStringValue:@"888-555-5512"] + messageNumber:[CNPhoneNumber phoneNumberWithStringValue:@"888-555-5512"] + emailAddress:@"mruiz2@mac.com" + monogram:@"MR" + image:nil]; + [contacts addObject:contact]; + } + + { + UIColor *color = GreenColor(); + OCKContact *contact = [[OCKContact alloc] initWithContactType:OCKContactTypeCareTeam + name:@"Bill James" + relation:@"Nurse" + tintColor:color + phoneNumber:[CNPhoneNumber phoneNumberWithStringValue:@"888-555-5512"] + messageNumber:[CNPhoneNumber phoneNumberWithStringValue:@"888-555-5512"] + emailAddress:@"billjames2@mac.com" + monogram:@"BJ" + image:nil]; + [contacts addObject:contact]; + } + + { + OCKContact *contact = [[OCKContact alloc] initWithContactType:OCKContactTypePersonal + name:@"Tom Clark" + relation:@"Father" + tintColor:nil + phoneNumber:[CNPhoneNumber phoneNumberWithStringValue:@"888-555-5512"] + messageNumber:[CNPhoneNumber phoneNumberWithStringValue:@"888-555-5512"] + emailAddress:nil + monogram:@"TC" + image:nil]; + [contacts addObject:contact]; + } + + _contacts = [contacts copy]; +} + + +#pragma mark - OCKConnectViewControllerDelegate + +- (NSString *)connectViewController:(OCKConnectViewController *)connectViewController titleForSharingCellForContact:(OCKContact *)contact { + NSString *title; + if (![contact isEqual:_contacts[1]]){ + title = @"Send weekly reports"; + } + return title; +} + +- (void)connectViewController:(OCKConnectViewController *)connectViewController didSelectShareButtonForContact:(OCKContact *)contact presentationSourceView:(UIView *)sourceView { + NSLog(@"Share button tapped"); +} + + +#pragma mark - UITableViewDataSource + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return TestItemCount; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; + + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + } + + NSString *title = @""; + switch (indexPath.row) { + case TestItemInsights: + title = @"Insights"; + break; + case TestItemBarChartView: + title = @"Bar Chart View"; + break; + case TestItemCareCard: + title = @"Care Card"; + break; + case TestItemCareCardCustom: + title = @"Care Card - Custom"; + break; + case TestItemSymptomTracker: + title = @"Symptom Tracker"; + break; + case TestItemConnectPage: + title = @"Connect Page"; + break; + case TestItemDocument: + title = @"PDF Document"; + break; + default: + title = @"Unknown"; + break; + } + cell.textLabel.text = title; + return cell; +} + + +#pragma mark - UITableViewDelegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + [self.navigationController pushViewController:[self viewControllerForTestItem:indexPath.row] animated:YES]; +} + +@end diff --git a/testing/OCKTest/OCKTest/SymptomTrackerTableViewController.swift b/testing/OCKTest/OCKTest/SymptomTrackerTableViewController.swift index 8cf49cb82..64dd1cd78 100644 --- a/testing/OCKTest/OCKTest/SymptomTrackerTableViewController.swift +++ b/testing/OCKTest/OCKTest/SymptomTrackerTableViewController.swift @@ -37,18 +37,18 @@ class SymptomTrackerTableViewController: UITableViewController, OCKSymptomTracke var healthKitStore:HKHealthStore? - override func numberOfSectionsInTableView(tableView: UITableView) -> Int { + override func numberOfSections(in tableView: UITableView) -> Int { return 1 } - override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 5 } - override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if let cell = tableView.dequeueReusableCellWithIdentifier("cell") { - switch indexPath.row { + if let cell = tableView.dequeueReusableCell(withIdentifier: "cell") { + switch (indexPath as NSIndexPath).row { case 0: cell.textLabel?.text = "No Delegate, No Edges" case 1: @@ -57,9 +57,9 @@ class SymptomTrackerTableViewController: UITableViewController, OCKSymptomTracke cell.textLabel?.text = "With Delegate" case 3: cell.textLabel?.text = "Track Health Data" - if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.Pad { - cell.textLabel?.textColor = UIColor.grayColor() - cell.userInteractionEnabled = false + if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad { + cell.textLabel?.textColor = UIColor.gray + cell.isUserInteractionEnabled = false } case 4: cell.textLabel?.text = "Delete all Activites" @@ -74,141 +74,138 @@ class SymptomTrackerTableViewController: UITableViewController, OCKSymptomTracke } - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let documentsDirectory = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true) + let documentsDirectory = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) - if indexPath.row == 0 { + if (indexPath as NSIndexPath).row == 0 { // No Delegate, No Edges - - let startDateComponents = NSDateComponents.init() + var startDateComponents = DateComponents.init() startDateComponents.day = 20 startDateComponents.month = 3 startDateComponents.year = 2000 - let schedule = OCKCareSchedule.dailyScheduleWithStartDate(startDateComponents, occurrencesPerDay: 1) + let schedule = OCKCareSchedule.dailySchedule(withStartDate: startDateComponents, occurrencesPerDay: 1) let firstGroupId = "Group A1" - let carePlanActivity1 = OCKCarePlanActivity.init(identifier: "Assessment Activity #1", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.Assessment, title: "Assessment Activity Title 1", text: "Read the instructions about this task", tintColor: UIColor.redColor(), instructions: "Perform the described task and report the results. Talk to your doctor if you need help", imageURL: nil, schedule: schedule, resultResettable: true, userInfo: ["Key1":"Value1","Key2":"Value2"]) + let carePlanActivity1 = OCKCarePlanActivity.init(identifier: "Assessment Activity #1", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.assessment, title: "Assessment Activity Title 1", text: "Read the instructions about this task", tintColor: UIColor.red, instructions: "Perform the described task and report the results. Talk to your doctor if you need help", imageURL: nil, schedule: schedule, resultResettable: true, userInfo: nil) - let carePlanActivity2 = OCKCarePlanActivity.init(identifier: "Assessment Activity #2", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.Assessment, title: "Assessment Activity Title 2", text: "Complete this activity ASAP", tintColor: UIColor.orangeColor(), instructions: nil, imageURL: nil, schedule: schedule, resultResettable: true, userInfo: ["Key1":"Value1","Key2":"Value2"]) + let carePlanActivity2 = OCKCarePlanActivity.init(identifier: "Assessment Activity #2", groupIdentifier: firstGroupId, type: OCKCarePlanActivityType.assessment, title: "Assessment Activity Title 2", text: "Complete this activity ASAP", tintColor: UIColor.orange, instructions: nil, imageURL: nil, schedule: schedule, resultResettable: true, userInfo: nil) - let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: NSURL.init(string: documentsDirectory[0])!) - carePlanStore .addActivity(carePlanActivity1, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: URL.init(string: documentsDirectory[0])!) + carePlanStore .add(carePlanActivity1, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) - carePlanStore .addActivity(carePlanActivity2, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + carePlanStore .add(carePlanActivity2, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) let symptomTracker = OCKSymptomTrackerViewController.init(carePlanStore: carePlanStore) self.navigationController?.pushViewController(symptomTracker, animated: true) - } else if indexPath.row == 1 { + } else if (indexPath as NSIndexPath).row == 1 { // No Activities - let dataPath = documentsDirectory[0].stringByAppendingString("/EmptyAssessmentPlan") - if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) { + let dataPath = documentsDirectory[0] + "/EmptyAssessmentPlan" + if !FileManager.default.fileExists(atPath: dataPath) { do { - try NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil) + try FileManager.default.createDirectory(atPath: dataPath, withIntermediateDirectories: false, attributes: nil) } catch(_) { assertionFailure("Unable to Create Directory for EmptyAssessmentPlan") } } - let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: NSURL.init(string: dataPath)!) + let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: URL.init(string: dataPath)!) let symptomTracker = OCKSymptomTrackerViewController.init(carePlanStore: carePlanStore) symptomTracker.showEdgeIndicators = true self.navigationController?.pushViewController(symptomTracker, animated: true) - } else if indexPath.row == 2 { + } else if (indexPath as NSIndexPath).row == 2 { // With Delegate - let startDateComponents = NSDateComponents.init() + var startDateComponents = DateComponents.init() startDateComponents.day = 20 startDateComponents.month = 3 startDateComponents.year = 0010 - let endDate = NSDate().dateByAddingTimeInterval(-86400.0) - let unitFlags: NSCalendarUnit = [.Day, .Month, .Year] - let endDateComponents = NSCalendar.currentCalendar().components(unitFlags, fromDate: endDate) + let endDate = Date().addingTimeInterval(-86400.0) + let endDateComponents = NSCalendar.current.dateComponents([.day, .month, .year], from: endDate) - let schedule1 = OCKCareSchedule.weeklyScheduleWithStartDate(startDateComponents, occurrencesOnEachDay: [1, 2, 3, 4, 5, 6, 7], weeksToSkip: 0, endDate: endDateComponents) - let schedule2 = OCKCareSchedule.dailyScheduleWithStartDate(startDateComponents, occurrencesPerDay: 1, daysToSkip: 0, endDate: nil) + let schedule1 = OCKCareSchedule.weeklySchedule(withStartDate: startDateComponents, occurrencesOnEachDay: [1, 2, 3, 4, 5, 6, 7], weeksToSkip: 0, endDate: endDateComponents) + let schedule2 = OCKCareSchedule.dailySchedule(withStartDate: startDateComponents, occurrencesPerDay: 1, daysToSkip: 0, endDate: nil) let secondGroupId = "Group A2" - let carePlanActivity1 = OCKCarePlanActivity.init(identifier: "Assessment Activity #1", groupIdentifier: secondGroupId, type: OCKCarePlanActivityType.Assessment, title: "Activity that ended yesterday ", text: "Read the instructions about this task", tintColor: nil, instructions: "Perform the described task and report the results. Talk to your doctor if you need help", imageURL: nil, schedule: schedule1, resultResettable: false, userInfo: ["Key1":"Value1","Key2":"Value2"]) + let carePlanActivity1 = OCKCarePlanActivity.init(identifier: "Assessment Activity #1", groupIdentifier: secondGroupId, type: OCKCarePlanActivityType.assessment, title: "Activity that ended yesterday ", text: "Read the instructions about this task", tintColor: nil, instructions: "Perform the described task and report the results. Talk to your doctor if you need help", imageURL: nil, schedule: schedule1, resultResettable: false, userInfo: nil) - let carePlanActivity2 = OCKCarePlanActivity.assessmentWithIdentifier("Assessment Activity #2", groupIdentifier: secondGroupId, title: "A Daily Activity is one that repeats every day", text: "This is an assessment. Be careful. You are being evaluated every single day.", tintColor: UIColor.purpleColor(), resultResettable: false, schedule: schedule2, userInfo: nil) + let carePlanActivity2 = OCKCarePlanActivity.assessment(withIdentifier: "Assessment Activity #2", groupIdentifier: secondGroupId, title: "A Daily Activity is one that repeats every day", text: "This is an assessment. Be careful. You are being evaluated every single day.", tintColor: UIColor.purple, resultResettable: false, schedule: schedule2, userInfo: nil) - let dataPath = documentsDirectory[0].stringByAppendingString("/CarePlan2") - if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) { + let dataPath = documentsDirectory[0] + "/CarePlan2" + if !FileManager.default.fileExists(atPath: dataPath) { do { - try NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil) + try FileManager.default.createDirectory(atPath: dataPath, withIntermediateDirectories: false, attributes: nil) } catch(_) { assertionFailure("Unable to Create Directory for CarePlan2") } } - let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: NSURL.init(string: dataPath)!) - carePlanStore.addActivity(carePlanActivity1, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: URL.init(string: dataPath)!) + carePlanStore.add(carePlanActivity1, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) - carePlanStore.addActivity(carePlanActivity2, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + carePlanStore.add(carePlanActivity2, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) let symptomTracker = OCKSymptomTrackerViewController.init(carePlanStore: carePlanStore) - symptomTracker.progressRingTintColor = UIColor.magentaColor() + symptomTracker.progressRingTintColor = UIColor.magenta symptomTracker.delegate = self symptomTracker.showEdgeIndicators = true self.navigationController?.pushViewController(symptomTracker, animated: true) - } else if indexPath.row == 3 { + } else if (indexPath as NSIndexPath).row == 3 { // Track Health Data - - self.authorizeHealthKit({ (success, error) in - assert(success, error.description) - dispatch_async(dispatch_get_main_queue()) { + self.authorizeHealthKit(completion: { (success, error) in + assert(success, (error?.localizedDescription)!) + DispatchQueue.main.async { self.saveHKSamples() } }) - let startDateComponents = NSDateComponents.init(year: 1, month: 1, day: 1) - let schedule = OCKCareSchedule.weeklyScheduleWithStartDate(startDateComponents, occurrencesOnEachDay: [1, 1, 1, 1, 1, 1, 1]) + let startDateComponents = DateComponents.init(year: 1, month: 1, day: 1) + let schedule = OCKCareSchedule.weeklySchedule(withStartDate: startDateComponents, occurrencesOnEachDay: [1, 1, 1, 1, 1, 1, 1]) - let dataPath = documentsDirectory[0].stringByAppendingString("/CarePlanHealth") - if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) { + let dataPath = documentsDirectory[0] + "/CarePlanHealth" + if !FileManager.default.fileExists(atPath: dataPath) { do { - try NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil) + try FileManager.default.createDirectory(atPath: dataPath, withIntermediateDirectories: false, attributes: nil) } catch(_) { assertionFailure("Unable to Create Directory for CarePlanHealth") } } - let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: NSURL.init(string: dataPath)!) + let carePlanStore = OCKCarePlanStore.init(persistenceDirectoryURL: URL.init(string: dataPath)!) let thirdGroupId = "Group A3" - let carePlanActivity1 = OCKCarePlanActivity.assessmentWithIdentifier("Step Count", groupIdentifier: thirdGroupId, title: "Step Count", text: "Get steps from Health app", tintColor: UIColor.init(red: 0.3, green: 0.2, blue: 0.9, alpha: 0.4), resultResettable: true, schedule: schedule, userInfo: ["Type":"Steps"]) - carePlanStore.addActivity(carePlanActivity1, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + let carePlanActivity1 = OCKCarePlanActivity.assessment(withIdentifier: "Step Count", groupIdentifier: thirdGroupId, title: "Step Count", text: "Get steps from Health app", tintColor: UIColor.init(red: 0.3, green: 0.2, blue: 0.9, alpha: 0.4), resultResettable: true, schedule: schedule, userInfo: ["Type":"Steps"]) + carePlanStore.add(carePlanActivity1, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) - let carePlanActivity2 = OCKCarePlanActivity.assessmentWithIdentifier("Body Fat", groupIdentifier: thirdGroupId, title: "Body Fat", text: "Get Body Fat from Health app", tintColor: UIColor.init(red: 0.3, green: 0.2, blue: 0.9, alpha: 0.4), resultResettable: true, schedule: schedule, userInfo: ["Type":"BodyFat"]) - carePlanStore.addActivity(carePlanActivity2, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + let carePlanActivity2 = OCKCarePlanActivity.assessment(withIdentifier: "Body Fat", groupIdentifier: thirdGroupId, title: "Body Fat", text: "Get Body Fat from Health app", tintColor: UIColor.init(red: 0.3, green: 0.2, blue: 0.9, alpha: 0.4), resultResettable: true, schedule: schedule, userInfo: ["Type":"BodyFat"]) + carePlanStore.add(carePlanActivity2, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) - let carePlanActivity3 = OCKCarePlanActivity.assessmentWithIdentifier("Sleep Analysis", groupIdentifier: thirdGroupId, title: "Sleep Analysis", text: "Get Sleep Data from Health app", tintColor: UIColor.init(red: 0.3, green: 0.2, blue: 0.9, alpha: 0.4), resultResettable: true, schedule: schedule, userInfo: ["Type":"Sleep"]) - carePlanStore.addActivity(carePlanActivity3, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + let carePlanActivity3 = OCKCarePlanActivity.assessment(withIdentifier: "Sleep Analysis", groupIdentifier: thirdGroupId, title: "Sleep Analysis", text: "Get Sleep Data from Health app", tintColor: UIColor.init(red: 0.3, green: 0.2, blue: 0.9, alpha: 0.4), resultResettable: true, schedule: schedule, userInfo: ["Type":"Sleep"]) + carePlanStore.add(carePlanActivity3, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) - let carePlanActivity4 = OCKCarePlanActivity.assessmentWithIdentifier("Ovulation", groupIdentifier: thirdGroupId, title: "Ovulation", text: "Get Ovulation Data from Health app", tintColor: UIColor.init(red: 0.3, green: 0.2, blue: 0.9, alpha: 0.4), resultResettable: true, schedule: schedule, userInfo: ["Type":"Ovulation"]) - carePlanStore.addActivity(carePlanActivity4, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + let carePlanActivity4 = OCKCarePlanActivity.assessment(withIdentifier: "Ovulation", groupIdentifier: thirdGroupId, title: "Ovulation", text: "Get Ovulation Data from Health app", tintColor: UIColor.init(red: 0.3, green: 0.2, blue: 0.9, alpha: 0.4), resultResettable: true, schedule: schedule, userInfo: ["Type":"Ovulation"]) + carePlanStore.add(carePlanActivity4, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) - let carePlanActivity5 = OCKCarePlanActivity.assessmentWithIdentifier("Blood Pressure", groupIdentifier: thirdGroupId, title: "Blood Pressure", text: "Get Blood Pressure from Health app", tintColor: UIColor.init(red: 0.3, green: 0.2, blue: 0.9, alpha: 0.4), resultResettable: true, schedule: schedule, userInfo: ["Type":"Blood Pressure"]) - carePlanStore.addActivity(carePlanActivity5, completion: { (boolVal, error) in - assert(boolVal, (error?.description)!) + let carePlanActivity5 = OCKCarePlanActivity.assessment(withIdentifier: "Blood Pressure", groupIdentifier: thirdGroupId, title: "Blood Pressure", text: "Get Blood Pressure from Health app", tintColor: UIColor.init(red: 0.3, green: 0.2, blue: 0.9, alpha: 0.4), resultResettable: true, schedule: schedule, userInfo: ["Type":"Blood Pressure"]) + carePlanStore.add(carePlanActivity5, completion: { (boolVal, error) in + assert(boolVal, (error?.localizedDescription)!) }) let symptomTracker = OCKSymptomTrackerViewController.init(carePlanStore: carePlanStore) @@ -217,58 +214,58 @@ class SymptomTrackerTableViewController: UITableViewController, OCKSymptomTracke symptomTracker.progressRingTintColor = UIColor.init(red: 0.3, green: 0.2, blue: 0.9, alpha: 0.4) self.navigationController?.pushViewController(symptomTracker, animated: true) - } else if indexPath.row == 4 { + } else if (indexPath as NSIndexPath).row == 4 { // Delete all Activites - tableView.cellForRowAtIndexPath(indexPath)?.selected = false - let store = OCKCarePlanStore.init(persistenceDirectoryURL: NSURL.init(string: documentsDirectory[0])!) + tableView.cellForRow(at: indexPath)?.isSelected = false + let store = OCKCarePlanStore.init(persistenceDirectoryURL: URL.init(string: documentsDirectory[0])!) - store.activitiesWithGroupIdentifier("Group A1", completion: { (boolVal, activities, error) in + store.activities(withGroupIdentifier: "Group A1", completion: { (boolVal, activities, error) in for activity:OCKCarePlanActivity in activities { - store.removeActivity(activity, completion: { (boolVal, error) in + store.remove(activity, completion: { (boolVal, error) in if boolVal == true { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.greenColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.green } else { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.redColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.red } - assert(boolVal, (error?.description)!) + assert(boolVal, (error?.localizedDescription)!) }) } }) - if NSFileManager.defaultManager().fileExistsAtPath(documentsDirectory[0].stringByAppendingString("/CarePlan2")) { - let dataPath = NSURL.init(string:documentsDirectory[0].stringByAppendingString("/CarePlan2")) + if FileManager.default.fileExists(atPath: documentsDirectory[0] + "/CarePlan2") { + let dataPath = URL.init(string:documentsDirectory[0] + "/CarePlan2") let store2 = OCKCarePlanStore.init(persistenceDirectoryURL: dataPath!) - store2.activitiesWithGroupIdentifier("Group A2", completion: { (boolVal, activities, error) in + store2.activities(withGroupIdentifier: "Group A2", completion: { (boolVal, activities, error) in for activity:OCKCarePlanActivity in activities { - store2.removeActivity(activity, completion: { (boolVal, error) in + store2.remove(activity, completion: { (boolVal, error) in if boolVal == true { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.greenColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.green } else { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.redColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.red } - assert(boolVal, (error?.description)!) + assert(boolVal, (error?.localizedDescription)!) }) } }) } - if NSFileManager.defaultManager().fileExistsAtPath(documentsDirectory[0].stringByAppendingString("/CarePlanHealth")) { - let dataPath = NSURL.init(string:documentsDirectory[0].stringByAppendingString("/CarePlanHealth")) + if FileManager.default.fileExists(atPath: documentsDirectory[0] + "/CarePlanHealth") { + let dataPath = URL.init(string:documentsDirectory[0] + "/CarePlanHealth") let store3 = OCKCarePlanStore.init(persistenceDirectoryURL:dataPath!) - store3.activitiesWithGroupIdentifier("Group A3", completion: { (boolVal, activities, error) in + store3.activities(withGroupIdentifier: "Group A3", completion: { (boolVal, activities, error) in for activity:OCKCarePlanActivity in activities { - store3.removeActivity(activity, completion: { (boolVal, error) in + store3.remove(activity, completion: { (boolVal, error) in if boolVal == true { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.greenColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.green } else { - tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.redColor() + tableView.cellForRow(at: indexPath)?.textLabel?.textColor = UIColor.red } - assert(boolVal, (error?.description)!) + assert(boolVal, (error?.localizedDescription)!) }) } }) @@ -276,60 +273,56 @@ class SymptomTrackerTableViewController: UITableViewController, OCKSymptomTracke } } - func authorizeHealthKit(completion: ((success:Bool, error:NSError!) -> Void)!) - { + func authorizeHealthKit(completion: ((_ success:Bool, _ error:Error?) -> Void)!) { healthKitStore = HKHealthStore() - let typesSet:Set = [HKCategoryType.categoryTypeForIdentifier(HKCategoryTypeIdentifierSleepAnalysis)!, HKCategoryType.categoryTypeForIdentifier(HKCategoryTypeIdentifierOvulationTestResult)!, HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount)!, HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyFatPercentage)!, HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBloodPressureSystolic)!, HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBloodPressureDiastolic)!] + let typesSet : Set = [HKCategoryType.categoryType(forIdentifier: HKCategoryTypeIdentifier.sleepAnalysis)!, HKCategoryType.categoryType(forIdentifier: HKCategoryTypeIdentifier.ovulationTestResult)!, HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!, HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyFatPercentage)!, HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureSystolic)!, HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureDiastolic)!] - healthKitStore?.requestAuthorizationToShareTypes(typesSet, readTypes: typesSet, completion: { (boolVal, error) in - completion(success: boolVal, error: error) - }) + healthKitStore?.requestAuthorization(toShare: typesSet, read: typesSet, completion: completion) } - func readHKSample(sampleType:HKSampleType , completion: ((HKSample!, NSError!) -> Void)!) - { + func readHKSample(_ sampleType:HKSampleType , completion: ((HKSample?, Error?) -> Void)!) { let sortDescriptor = NSSortDescriptor(key:HKSampleSortIdentifierStartDate, ascending: false) let limit = 1 let sampleQuery = HKSampleQuery(sampleType: sampleType, predicate: nil, limit: limit, sortDescriptors: [sortDescriptor]) { (sampleQuery, results, error ) -> Void in - if let failureDescription = error?.description { assertionFailure(failureDescription) } + if let failureDescription = error?.localizedDescription { assertionFailure(failureDescription) } let mostRecentSample = results!.first if completion != nil { completion(mostRecentSample,nil) } } - healthKitStore!.executeQuery(sampleQuery) + healthKitStore!.execute(sampleQuery) } func saveHKSamples() { - let stepCountType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount)! - let numSteps = HKQuantity(unit: HKUnit.countUnit(), doubleValue: 10000) - let stepsSample = HKQuantitySample(type: stepCountType, quantity: numSteps, startDate: NSDate(), endDate: NSDate()) + let stepCountType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)! + let numSteps = HKQuantity(unit: HKUnit.count(), doubleValue: 10000) + let stepsSample = HKQuantitySample(type: stepCountType, quantity: numSteps, start: Date(), end: Date()) - let bodyFatType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyFatPercentage)! - let bodyFatPercentage = HKQuantity(unit: HKUnit.percentUnit(), doubleValue: 0.25) - let bodyFatSample = HKQuantitySample(type: bodyFatType, quantity: bodyFatPercentage, startDate: NSDate(), endDate: NSDate()) + let bodyFatType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyFatPercentage)! + let bodyFatPercentage = HKQuantity(unit: HKUnit.percent(), doubleValue: 0.25) + let bodyFatSample = HKQuantitySample(type: bodyFatType, quantity: bodyFatPercentage, start: Date(), end: Date()) - let sleepType = HKCategoryType.categoryTypeForIdentifier(HKCategoryTypeIdentifierSleepAnalysis)! - let sleepSample = HKCategorySample(type: sleepType, value: 1, startDate: NSDate(), endDate: NSDate()) + let sleepType = HKCategoryType.categoryType(forIdentifier: HKCategoryTypeIdentifier.sleepAnalysis)! + let sleepSample = HKCategorySample(type: sleepType, value: 1, start: Date(), end: Date()) - let ovulationType = HKCategoryType.categoryTypeForIdentifier(HKCategoryTypeIdentifierOvulationTestResult)! - let ovulationSample = HKCategorySample(type: ovulationType, value: 1, startDate: NSDate(), endDate: NSDate()) + let ovulationType = HKCategoryType.categoryType(forIdentifier: HKCategoryTypeIdentifier.ovulationTestResult)! + let ovulationSample = HKCategorySample(type: ovulationType, value: 1, start: Date(), end: Date()) - let diastolicBPType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBloodPressureDiastolic)! - let diastolicBP = HKQuantity(unit: HKUnit.millimeterOfMercuryUnit(), doubleValue: 80) - let diastolicBPSample = HKQuantitySample(type: diastolicBPType, quantity: diastolicBP, startDate: NSDate(), endDate: NSDate()) + let diastolicBPType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureDiastolic)! + let diastolicBP = HKQuantity(unit: HKUnit.millimeterOfMercury(), doubleValue: 80) + let diastolicBPSample = HKQuantitySample(type: diastolicBPType, quantity: diastolicBP, start: Date(), end: Date()) - let systolicBPType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBloodPressureSystolic)! - let systolicBP = HKQuantity(unit: HKUnit.millimeterOfMercuryUnit(), doubleValue: 120) - let systolicBPSample = HKQuantitySample(type: systolicBPType, quantity: systolicBP, startDate: NSDate(), endDate: NSDate()) + let systolicBPType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureSystolic)! + let systolicBP = HKQuantity(unit: HKUnit.millimeterOfMercury(), doubleValue: 120) + let systolicBPSample = HKQuantitySample(type: systolicBPType, quantity: systolicBP, start: Date(), end: Date()) - let bpSample = HKCorrelation(type: HKCorrelationType.correlationTypeForIdentifier(HKCorrelationTypeIdentifierBloodPressure)!, startDate: NSDate(), endDate: NSDate(), objects: [systolicBPSample, diastolicBPSample]) + let bpSample = HKCorrelation(type: HKCorrelationType.correlationType(forIdentifier: HKCorrelationTypeIdentifier.bloodPressure)!, start: Date(), end: Date(), objects: [systolicBPSample, diastolicBPSample]) - healthKitStore?.saveObjects([stepsSample, bodyFatSample, sleepSample, ovulationSample, bpSample], withCompletion: { (success, error) in + healthKitStore?.save([stepsSample, bodyFatSample, sleepSample, ovulationSample, bpSample], withCompletion: { (success, error) in if success == false { print("Error saving Health Samples: \(error?.localizedDescription)") } else { @@ -338,91 +331,91 @@ class SymptomTrackerTableViewController: UITableViewController, OCKSymptomTracke }) } - func symptomTrackerViewController(viewController: OCKSymptomTrackerViewController, didSelectRowWithAssessmentEvent assessmentEvent: OCKCarePlanEvent) { + func symptomTrackerViewController(_ viewController: OCKSymptomTrackerViewController, didSelectRowWithAssessmentEvent assessmentEvent: OCKCarePlanEvent) { if viewController.progressRingTintColor == UIColor.init(red: 0.3, green: 0.2, blue: 0.9, alpha: 0.4) { - if String(assessmentEvent.activity.userInfo!["Type"]!) == "Steps" { - if (healthKitStore?.authorizationStatusForType(HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount)!)) == HKAuthorizationStatus.SharingAuthorized { - self.readHKSample(HKQuantityType.quantityTypeForIdentifier( - HKQuantityTypeIdentifierStepCount)!, completion: { (sample, error) in - let qResult = OCKCarePlanEventResult.init(quantitySample: sample as! HKQuantitySample, quantityStringFormatter: nil, unitStringKeys: [HKUnit.countUnit():"Steps Today"], userInfo: nil) - viewController.store.updateEvent(assessmentEvent, withResult: qResult, state: OCKCarePlanEventState.Completed, completion: { (boolVal, event, error) in + if String(describing: assessmentEvent.activity.userInfo!["Type"]!) == "Steps" { + if (healthKitStore?.authorizationStatus(for: HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!)) == HKAuthorizationStatus.sharingAuthorized { + self.readHKSample(HKQuantityType.quantityType( + forIdentifier: HKQuantityTypeIdentifier.stepCount)!, completion: { (sample, error) in + let qResult = OCKCarePlanEventResult.init(quantitySample: sample as! HKQuantitySample, quantityStringFormatter: nil, unitStringKeys: [HKUnit.count():"Steps Today"], userInfo: nil) + viewController.store.update(assessmentEvent, with: qResult, state: OCKCarePlanEventState.completed, completion: { (boolVal, event, error) in }) }) } - } else if String(assessmentEvent.activity.userInfo!["Type"]!) == "BodyFat" { - if (healthKitStore?.authorizationStatusForType(HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyFatPercentage)!)) == HKAuthorizationStatus.SharingAuthorized { - self.readHKSample(HKQuantityType.quantityTypeForIdentifier( - HKQuantityTypeIdentifierBodyFatPercentage)!, completion: { (sample, error) in - let qResult = OCKCarePlanEventResult.init(quantitySample: sample as! HKQuantitySample, quantityStringFormatter: nil, displayUnit: HKUnit.percentUnit(), displayUnitStringKey: "X100 %", userInfo: nil) - viewController.store.updateEvent(assessmentEvent, withResult: qResult, state: OCKCarePlanEventState.Completed, completion: { (boolVal, event, error) in - assert(boolVal, (error?.description)!) + } else if String(describing: assessmentEvent.activity.userInfo!["Type"]!) == "BodyFat" { + if (healthKitStore?.authorizationStatus(for: HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyFatPercentage)!)) == HKAuthorizationStatus.sharingAuthorized { + self.readHKSample(HKQuantityType.quantityType( + forIdentifier: HKQuantityTypeIdentifier.bodyFatPercentage)!, completion: { (sample, error) in + let qResult = OCKCarePlanEventResult.init(quantitySample: sample as! HKQuantitySample, quantityStringFormatter: nil, display: HKUnit.percent(), displayUnitStringKey: "X100 %", userInfo: nil) + viewController.store.update(assessmentEvent, with: qResult, state: OCKCarePlanEventState.completed, completion: { (boolVal, event, error) in + assert(boolVal, (error?.localizedDescription)!) }) }) } - } else if String(assessmentEvent.activity.userInfo!["Type"]!) == "Sleep" { - if (healthKitStore?.authorizationStatusForType(HKCategoryType.categoryTypeForIdentifier(HKCategoryTypeIdentifierSleepAnalysis)!)) == HKAuthorizationStatus.SharingAuthorized { - self.readHKSample(HKCategoryType.categoryTypeForIdentifier(HKCategoryTypeIdentifierSleepAnalysis)!, completion: { (sample, error) in + } else if String(describing: assessmentEvent.activity.userInfo!["Type"]!) == "Sleep" { + if (healthKitStore?.authorizationStatus(for: HKCategoryType.categoryType(forIdentifier: HKCategoryTypeIdentifier.sleepAnalysis)!)) == HKAuthorizationStatus.sharingAuthorized { + self.readHKSample(HKCategoryType.categoryType(forIdentifier: HKCategoryTypeIdentifier.sleepAnalysis)!, completion: { (sample, error) in let catResult = OCKCarePlanEventResult.init(categorySample: sample as! HKCategorySample, categoryValueStringKeys: [0 : "In Bed", 1 : "Asleep"], userInfo: nil) - viewController.store.updateEvent(assessmentEvent, withResult: catResult, state: OCKCarePlanEventState.Completed, completion: { (boolVal, event, error) in - assert(boolVal, (error?.description)!) + viewController.store.update(assessmentEvent, with: catResult, state: OCKCarePlanEventState.completed, completion: { (boolVal, event, error) in + assert(boolVal, (error?.localizedDescription)!) }) }) } - } else if String(assessmentEvent.activity.userInfo!["Type"]!) == "Ovulation" { - if (healthKitStore?.authorizationStatusForType(HKCategoryType.categoryTypeForIdentifier(HKCategoryTypeIdentifierOvulationTestResult)!)) == HKAuthorizationStatus.SharingAuthorized { - self.readHKSample(HKCategoryType.categoryTypeForIdentifier(HKCategoryTypeIdentifierOvulationTestResult)!, completion: { (sample, error) in + } else if String(describing: assessmentEvent.activity.userInfo!["Type"]!) == "Ovulation" { + if (healthKitStore?.authorizationStatus(for: HKCategoryType.categoryType(forIdentifier: HKCategoryTypeIdentifier.ovulationTestResult)!)) == HKAuthorizationStatus.sharingAuthorized { + self.readHKSample(HKCategoryType.categoryType(forIdentifier: HKCategoryTypeIdentifier.ovulationTestResult)!, completion: { (sample, error) in let catResult = OCKCarePlanEventResult.init(categorySample: sample as! HKCategorySample, categoryValueStringKeys: [1 : "Negative", 2 : "Positive", 3 : "Intermediate"], userInfo: nil) - viewController.store.updateEvent(assessmentEvent, withResult: catResult, state: OCKCarePlanEventState.Completed, completion: { (boolVal, event, error) in - assert(boolVal, (error?.description)!) + viewController.store.update(assessmentEvent, with: catResult, state: OCKCarePlanEventState.completed, completion: { (boolVal, event, error) in + assert(boolVal, (error?.localizedDescription)!) }) }) } - } else if String(assessmentEvent.activity.userInfo!["Type"]!) == "Blood Pressure" { - if (healthKitStore?.authorizationStatusForType(HKCorrelationType.correlationTypeForIdentifier(HKCorrelationTypeIdentifierBloodPressure)!)) == HKAuthorizationStatus.SharingAuthorized { - self.readHKSample(HKCorrelationType.correlationTypeForIdentifier(HKCorrelationTypeIdentifierBloodPressure)!, completion: { (sample, error) in - let correlationResult = OCKCarePlanEventResult.init(correlation: sample as! HKCorrelation, quantityStringFormatter: nil, displayUnit: HKUnit.millimeterOfMercuryUnit(), unitStringKeys: [HKUnit.millimeterOfMercuryUnit():"mm"], userInfo: nil) - viewController.store.updateEvent(assessmentEvent, withResult: correlationResult, state: OCKCarePlanEventState.Completed, completion: { (boolVal, event, error) in - assert(boolVal, (error?.description)!) + } else if String(describing: assessmentEvent.activity.userInfo!["Type"]!) == "Blood Pressure" { + if (healthKitStore?.authorizationStatus(for: HKCorrelationType.correlationType(forIdentifier: HKCorrelationTypeIdentifier.bloodPressure)!)) == HKAuthorizationStatus.sharingAuthorized { + self.readHKSample(HKCorrelationType.correlationType(forIdentifier: HKCorrelationTypeIdentifier.bloodPressure)!, completion: { (sample, error) in + let correlationResult = OCKCarePlanEventResult.init(correlation: sample as! HKCorrelation, quantityStringFormatter: nil, display: HKUnit.millimeterOfMercury(), unitStringKeys: [HKUnit.millimeterOfMercury():"mm"], userInfo: nil) + viewController.store.update(assessmentEvent, with: correlationResult, state: OCKCarePlanEventState.completed, completion: { (boolVal, event, error) in + assert(boolVal, (error?.localizedDescription)!) }) }) } } } else { - if assessmentEvent.state == OCKCarePlanEventState.Initial || assessmentEvent.state == OCKCarePlanEventState.NotCompleted { + if assessmentEvent.state == OCKCarePlanEventState.initial || assessmentEvent.state == OCKCarePlanEventState.notCompleted { let result = OCKCarePlanEventResult.init(valueString: "Value", unitString: "200g", userInfo: nil) - viewController.store.updateEvent(assessmentEvent, withResult: result, state: OCKCarePlanEventState.Completed) { (boolVal, carePlanEvent, error) in + viewController.store.update(assessmentEvent, with: result, state: OCKCarePlanEventState.completed) { (boolVal, carePlanEvent, error) in if error != nil { - print("Failed "+error!.description) + print("Failed "+error!.localizedDescription) } else { print("Symptom Event Details\n") print("Occurence: " + String(carePlanEvent!.occurrenceIndexOfDay)) print("Days Since Start: " + String(carePlanEvent!.numberOfDaysSinceStart)) - print("Date: " + String(carePlanEvent!.date)) + print("Date: " + String(describing: carePlanEvent!.date)) print("Activity: " + String(carePlanEvent!.activity.title)) print("State: " + String(carePlanEvent!.state.rawValue)) print("Result Value: " + String(result.valueString)) - print("Result Unit: " + String(result.unitString)) - print("Result Creation: " + String(result.creationDate)) + print("Result Unit: " + String(describing: result.unitString)) + print("Result Creation: " + String(describing: result.creationDate)) } } } else { let result = OCKCarePlanEventResult.init(valueString: "", unitString: nil, userInfo: nil) - viewController.store.updateEvent(assessmentEvent, withResult: result, state: OCKCarePlanEventState.NotCompleted) { (boolVal, carePlanEvent, error) in + viewController.store.update(assessmentEvent, with: result, state: OCKCarePlanEventState.notCompleted) { (boolVal, carePlanEvent, error) in if error != nil { - print("Failed " + error!.description) + print("Failed " + error!.localizedDescription) } else { print("Symptom Event Details\n") print("Occurence: " + String(carePlanEvent!.occurrenceIndexOfDay)) print("Days Since Start: " + String(carePlanEvent!.numberOfDaysSinceStart)) - print("Date: " + String(carePlanEvent!.date)) + print("Date: " + String(describing: carePlanEvent!.date)) print("Activity: " + String(carePlanEvent!.activity.title)) print("State: " + String(carePlanEvent!.state.rawValue)) print("Result Value: " + String(result.valueString)) - print("Result Unit: " + String(result.unitString)) - print("Result Creation: " + String(result.creationDate)) + print("Result Unit: " + String(describing: result.unitString)) + print("Result Creation: " + String(describing: result.creationDate)) } } } diff --git a/testing/OCKTest/OCKTest/ar.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/ar.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/ar.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/ar.lproj/Main.strings b/testing/OCKTest/OCKTest/ar.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/ar.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/ca.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/ca.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/ca.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/ca.lproj/Main.strings b/testing/OCKTest/OCKTest/ca.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/ca.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/cs.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/cs.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/cs.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/cs.lproj/Main.strings b/testing/OCKTest/OCKTest/cs.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/cs.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/da-DK.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/da-DK.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/da-DK.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/da-DK.lproj/Main.strings b/testing/OCKTest/OCKTest/da-DK.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/da-DK.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/da.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/da.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/da.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/da.lproj/Main.strings b/testing/OCKTest/OCKTest/da.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/da.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/de.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/de.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/de.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/de.lproj/Main.strings b/testing/OCKTest/OCKTest/de.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/de.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/el.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/el.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/el.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/el.lproj/Main.strings b/testing/OCKTest/OCKTest/el.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/el.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/en-AU.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/en-AU.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/en-AU.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/en-AU.lproj/Main.strings b/testing/OCKTest/OCKTest/en-AU.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/en-AU.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/en-GB.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/en-GB.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/en-GB.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/en-GB.lproj/Main.strings b/testing/OCKTest/OCKTest/en-GB.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/en-GB.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/es-MX.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/es-MX.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/es-MX.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/es-MX.lproj/Main.strings b/testing/OCKTest/OCKTest/es-MX.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/es-MX.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/es.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/es.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/es.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/es.lproj/Main.strings b/testing/OCKTest/OCKTest/es.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/es.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/fi-FI.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/fi-FI.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/fi-FI.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/fi-FI.lproj/Main.strings b/testing/OCKTest/OCKTest/fi-FI.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/fi-FI.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/fi.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/fi.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/fi.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/fi.lproj/Main.strings b/testing/OCKTest/OCKTest/fi.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/fi.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/fr-CA.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/fr-CA.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/fr-CA.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/fr-CA.lproj/Main.strings b/testing/OCKTest/OCKTest/fr-CA.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/fr-CA.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/fr.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/fr.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/fr.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/fr.lproj/Main.strings b/testing/OCKTest/OCKTest/fr.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/fr.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/he.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/he.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/he.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/he.lproj/Main.strings b/testing/OCKTest/OCKTest/he.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/he.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/hi.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/hi.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/hi.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/hi.lproj/Main.strings b/testing/OCKTest/OCKTest/hi.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/hi.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/hr.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/hr.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/hr.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/hr.lproj/Main.strings b/testing/OCKTest/OCKTest/hr.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/hr.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/hu-HU.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/hu-HU.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/hu-HU.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/hu-HU.lproj/Main.strings b/testing/OCKTest/OCKTest/hu-HU.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/hu-HU.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/hu.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/hu.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/hu.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/hu.lproj/Main.strings b/testing/OCKTest/OCKTest/hu.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/hu.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/id.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/id.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/id.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/id.lproj/Main.strings b/testing/OCKTest/OCKTest/id.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/id.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/it.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/it.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/it.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/it.lproj/Main.strings b/testing/OCKTest/OCKTest/it.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/it.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/ja.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/ja.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/ja.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/ja.lproj/Main.strings b/testing/OCKTest/OCKTest/ja.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/ja.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/ko.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/ko.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/ko.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/ko.lproj/Main.strings b/testing/OCKTest/OCKTest/ko.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/ko.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/main.m b/testing/OCKTest/OCKTest/main.m new file mode 100644 index 000000000..19e951aab --- /dev/null +++ b/testing/OCKTest/OCKTest/main.m @@ -0,0 +1,40 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import "AppDelegate.h" + + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/testing/OCKTest/OCKTest/ms.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/ms.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/ms.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/ms.lproj/Main.strings b/testing/OCKTest/OCKTest/ms.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/ms.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/nb.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/nb.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/nb.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/nb.lproj/Main.strings b/testing/OCKTest/OCKTest/nb.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/nb.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/nl.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/nl.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/nl.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/nl.lproj/Main.strings b/testing/OCKTest/OCKTest/nl.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/nl.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/pl.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/pl.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/pl.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/pl.lproj/Main.strings b/testing/OCKTest/OCKTest/pl.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/pl.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/pt-PT.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/pt-PT.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/pt-PT.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/pt-PT.lproj/Main.strings b/testing/OCKTest/OCKTest/pt-PT.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/pt-PT.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/pt.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/pt.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/pt.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/pt.lproj/Main.strings b/testing/OCKTest/OCKTest/pt.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/pt.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/ro.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/ro.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/ro.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/ro.lproj/Main.strings b/testing/OCKTest/OCKTest/ro.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/ro.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/ru.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/ru.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/ru.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/ru.lproj/Main.strings b/testing/OCKTest/OCKTest/ru.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/ru.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/sk.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/sk.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/sk.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/sk.lproj/Main.strings b/testing/OCKTest/OCKTest/sk.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/sk.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/sv.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/sv.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/sv.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/sv.lproj/Main.strings b/testing/OCKTest/OCKTest/sv.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/sv.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/th.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/th.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/th.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/th.lproj/Main.strings b/testing/OCKTest/OCKTest/th.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/th.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/tr.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/tr.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/tr.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/tr.lproj/Main.strings b/testing/OCKTest/OCKTest/tr.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/tr.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/uk.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/uk.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/uk.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/uk.lproj/Main.strings b/testing/OCKTest/OCKTest/uk.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/uk.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/vi.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/vi.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/vi.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/vi.lproj/Main.strings b/testing/OCKTest/OCKTest/vi.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/vi.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/zh-HK.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/zh-HK.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/zh-HK.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/zh-HK.lproj/Main.strings b/testing/OCKTest/OCKTest/zh-HK.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/zh-HK.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/zh-Hans.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/zh-Hans.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/zh-Hans.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/zh-Hans.lproj/Main.strings b/testing/OCKTest/OCKTest/zh-Hans.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/zh-Hans.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTest/zh-Hant.lproj/LaunchScreen.strings b/testing/OCKTest/OCKTest/zh-Hant.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/testing/OCKTest/OCKTest/zh-Hant.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/testing/OCKTest/OCKTest/zh-Hant.lproj/Main.strings b/testing/OCKTest/OCKTest/zh-Hant.lproj/Main.strings new file mode 100644 index 000000000..abc22657a --- /dev/null +++ b/testing/OCKTest/OCKTest/zh-Hant.lproj/Main.strings @@ -0,0 +1,3 @@ + +/* Class = "UIViewController"; title = "Navigation"; ObjectID = "BYZ-38-t0r"; */ +"BYZ-38-t0r.title" = "Navigation"; diff --git a/testing/OCKTest/OCKTestTests/Info.plist b/testing/OCKTest/OCKTestTests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/testing/OCKTest/OCKTestTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/testing/OCKTest/OCKTestTests/OCKTestTests.m b/testing/OCKTest/OCKTestTests/OCKTestTests.m new file mode 100644 index 000000000..ff7c3fdc2 --- /dev/null +++ b/testing/OCKTest/OCKTestTests/OCKTestTests.m @@ -0,0 +1,356 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import +#import + + +@interface OCKTestTests : XCTestCase + +@end + +@implementation OCKTestTests { + OCKCarePlanStore *_store; + OCKCarePlanActivity *_activity; + OCKCarePlanEvent *_event; + NSDateComponents *_startDate; +} + +- (void)setUp { + [super setUp]; + + NSURL *directoryURL = [NSURL fileURLWithPath:[self cleanTestPath]]; + _store = [[OCKCarePlanStore alloc] initWithPersistenceDirectoryURL:directoryURL]; + + _startDate = [[NSDateComponents alloc] initWithYear:2016 month:01 day:01]; + + OCKCareSchedule *schedule = [OCKCareSchedule dailyScheduleWithStartDate:_startDate occurrencesPerDay:6]; + + _activity = [OCKCarePlanActivity interventionWithIdentifier:@"id1" + groupIdentifier:@"gid1" + title:@"title1" + text:@"text1" + tintColor:[UIColor redColor] + instructions:@"detailText1" + imageURL:[NSURL fileURLWithPath:@"1.png"] + schedule:schedule + userInfo:@{@"key":@"value1"}]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"add1"]; + [_store addActivity:_activity completion:^(BOOL success, NSError * _Nonnull error) { + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:1.0 handler:^(NSError * _Nullable error) { + XCTAssertNil(error); + }]; + + + expectation = [self expectationWithDescription:@"events"]; + + __block NSArray *myevents = nil; + [_store eventsForActivity:_activity date:_startDate completion:^(NSArray * _Nonnull events, NSError * _Nullable error) { + [expectation fulfill]; + myevents = events; + }]; + [self waitForExpectationsWithTimeout:1.0 handler:^(NSError * _Nullable error) { + XCTAssertNil(error); + }]; + + _event = myevents.firstObject; +} + +- (void)tearDown { + [self cleanTestPath]; +} + + +- (NSString *)testPath { + NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *docPath = [searchPaths objectAtIndex:0]; + NSString *storePath = [docPath stringByAppendingPathComponent:@"carePlanStore"]; + [[NSFileManager defaultManager] createDirectoryAtPath:storePath withIntermediateDirectories:YES attributes:nil error:nil]; + + return storePath; +} + +- (NSString *)cleanTestPath { + NSString *testPath = [self testPath]; + [[NSFileManager defaultManager] removeItemAtPath:testPath error:nil]; + return [self testPath]; +} + +- (void)verifySample:(HKSample *)sample + formatter:(NSNumberFormatter *)formatter + unit:(HKUnit *)unit + unitStringKeys:(NSDictionary *)unitStringKeys + expectedString:(NSString *)expectedString + expectedUnit:(NSString *)expectedUnit { + [self verifySample:sample formatter:formatter unit:unit unitStringKeys:unitStringKeys expectedString:expectedString expectedUnit:expectedUnit saveToHK:YES]; +} + +- (void)verifySample:(HKSample *)sample + formatter:(NSNumberFormatter *)formatter + unit:(HKUnit *)unit + unitStringKeys:(NSDictionary *)unitStringKeys + expectedString:(NSString *)expectedString + expectedUnit:(NSString *)expectedUnit + saveToHK:(BOOL)saveToHK { + + XCTAssertTrue([HKHealthStore isHealthDataAvailable]); + + HKHealthStore *hkstore = [HKHealthStore new]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"requestAuthorization"]; + + if ([sample isKindOfClass:[HKCorrelation class]]) { + + HKQuantityType *systolicType = + [HKObjectType quantityTypeForIdentifier: + HKQuantityTypeIdentifierBloodPressureSystolic]; + + HKQuantityType *diastolicType = + [HKObjectType quantityTypeForIdentifier: + HKQuantityTypeIdentifierBloodPressureDiastolic]; + + [hkstore requestAuthorizationToShareTypes:[NSSet setWithObjects:systolicType, diastolicType , nil] + readTypes:[NSSet setWithObjects:systolicType, diastolicType , nil] + completion:^(BOOL success, NSError * _Nullable error) { + [expectation fulfill]; + }]; + + + } else { + [hkstore requestAuthorizationToShareTypes:[NSSet setWithObject:sample.sampleType] + readTypes:[NSSet setWithObject:sample.sampleType] completion:^(BOOL success, NSError * _Nullable error) { + [expectation fulfill]; + }]; + } + + [self waitForExpectationsWithTimeout:2500 handler:^(NSError * _Nullable error) { + XCTAssertNil(error); + }]; + + if (saveToHK) { + expectation = [self expectationWithDescription:@"save sample"]; + [hkstore saveObject:sample withCompletion:^(BOOL success, NSError * _Nullable error) { + [expectation fulfill]; + XCTAssertTrue(success); + }]; + [self waitForExpectationsWithTimeout:1.0 handler:^(NSError * _Nullable error) { + XCTAssertNil(error); + }]; + } + + OCKCarePlanEvent *sampleEvent = _event; + + OCKCarePlanEventResult *result = nil; + if ([sample isKindOfClass:[HKQuantitySample class]]) { + + if (unit) { + result = [[OCKCarePlanEventResult alloc] initWithQuantitySample:(HKQuantitySample *)sample + quantityStringFormatter:formatter + displayUnit:unit + displayUnitStringKey:unitStringKeys[unit] + userInfo:nil]; + } else { + result = [[OCKCarePlanEventResult alloc] initWithQuantitySample:(HKQuantitySample *)sample + quantityStringFormatter:formatter + unitStringKeys:unitStringKeys + userInfo:nil]; + } + XCTAssertNotNil(result.unitString); + } else if ([sample isKindOfClass:[HKCorrelation class]]) { + result = [[OCKCarePlanEventResult alloc] initWithCorrelation:(HKCorrelation *)sample + quantityStringFormatter:formatter + displayUnit:unit + unitStringKeys:unitStringKeys + userInfo:nil]; + XCTAssertNotNil(result.unitString); + } else if ([sample isKindOfClass:[HKCategorySample class]]) { + result = [[OCKCarePlanEventResult alloc] initWithCategorySample:(HKCategorySample *)sample + categoryValueStringKeys:@{@0:@"0a", @1:@"1b", @2:@"2c", @3:@"3d"} + userInfo:nil]; + } + + XCTAssertNotNil(result.valueString); + + expectation = [self expectationWithDescription:@"save result"]; + [_store updateEvent:sampleEvent + withResult:result + state:OCKCarePlanEventStateCompleted + completion:^(BOOL success, OCKCarePlanEvent * _Nullable event, NSError * _Nullable error) { + [expectation fulfill]; + XCTAssertTrue(success); + }]; + [self waitForExpectationsWithTimeout:1.0 handler:^(NSError * _Nullable error) { + XCTAssertNil(error); + }]; + + expectation = [self expectationWithDescription:@"read result"]; + __block OCKCarePlanEvent *fetchedEvent; + [_store enumerateEventsOfActivity:_activity + startDate:_startDate + endDate:_startDate + handler:^(OCKCarePlanEvent * _Nullable event, BOOL * _Nonnull stop) { + if (event.numberOfDaysSinceStart == sampleEvent.numberOfDaysSinceStart && + event.occurrenceIndexOfDay == sampleEvent.occurrenceIndexOfDay) { + fetchedEvent = event; + } + } + completion:^(BOOL completed, NSError * _Nullable error) { + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:30.0 handler:^(NSError * _Nullable error) { + XCTAssertNil(error); + }]; + + XCTAssertNotNil(fetchedEvent); + + NSLog(@"\n==========\n"); + NSLog(@"expectedString = %@", expectedString); + NSLog(@"valueString = %@", fetchedEvent.result.valueString); + NSLog(@"inputUnit = %@", [unit unitString]); + NSLog(@"expectedUnit = %@", expectedUnit); + NSLog(@"unitString = %@", fetchedEvent.result.unitString); + + XCTAssertEqualObjects(fetchedEvent.result.valueString, expectedString); + XCTAssertEqualObjects(fetchedEvent.result.unitString, expectedUnit); +} + +- (void)testHKResult { + + // HKQuantitySample + { + HKQuantityType* type = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass]; + HKUnit *gramUnit = [HKUnit gramUnit]; + HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type + quantity:[HKQuantity quantityWithUnit:gramUnit doubleValue:160.0] + startDate:[NSDate date] + endDate:[NSDate date]]; + + [self verifySample:sample formatter:nil unit:gramUnit unitStringKeys:@{gramUnit: gramUnit.unitString} + expectedString:@"160" expectedUnit:[[HKUnit gramUnit] unitString]]; + + [self verifySample:sample + formatter:nil + unit:nil + unitStringKeys:@{[HKUnit poundUnit]: @"pound"} + expectedString:@"0.353" + expectedUnit: @"pound"]; + + NSNumberFormatter *formatter = [NSNumberFormatter new]; + formatter.numberStyle = NSNumberFormatterCurrencyStyle; + + [self verifySample:sample + formatter:formatter + unit:nil + unitStringKeys:@{[HKUnit poundUnit]: [[HKUnit poundUnit] unitString]} + expectedString:@"$0.35" + expectedUnit:[[HKUnit poundUnit] unitString]]; + } + + // HKCategorySample + { + HKCategorySample *sample = [HKCategorySample categorySampleWithType:[HKCategoryType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis] + value:HKCategoryValueSleepAnalysisInBed + startDate:[NSDate date] + endDate:[NSDate dateWithTimeIntervalSinceNow:60]]; + + [self verifySample:sample formatter:nil unit:nil unitStringKeys:nil expectedString:@"0a" expectedUnit:nil]; + + HKCategorySample *sample2 = [HKCategorySample categorySampleWithType:[HKCategoryType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis] + value:HKCategoryValueSleepAnalysisAsleep + startDate:[NSDate date] + endDate:[NSDate dateWithTimeIntervalSinceNow:60]]; + + [self verifySample:sample2 formatter:nil unit:nil unitStringKeys:nil expectedString:@"1b" expectedUnit:nil]; + } + + // HKCorrelation + { + HKQuantityType *systolicType = + [HKObjectType quantityTypeForIdentifier: + HKQuantityTypeIdentifierBloodPressureSystolic]; + + HKQuantity *systolicQuantity = + [HKQuantity quantityWithUnit:[HKUnit millimeterOfMercuryUnit] + doubleValue:120.0]; + + HKQuantitySample *systolicSample = + [HKQuantitySample quantitySampleWithType:systolicType + quantity:systolicQuantity + startDate:[NSDate date] + endDate:[NSDate date]]; + + HKQuantityType *diastolicType = + [HKObjectType quantityTypeForIdentifier: + HKQuantityTypeIdentifierBloodPressureDiastolic]; + + HKQuantity *diastolicQuantity = + [HKQuantity quantityWithUnit:[HKUnit millimeterOfMercuryUnit] + doubleValue:75.0]; + + HKQuantitySample *diastolicSample = + [HKQuantitySample quantitySampleWithType:diastolicType + quantity:diastolicQuantity + startDate:[NSDate date] + endDate:[NSDate date]]; + + + + HKCorrelation *correlation = [HKCorrelation correlationWithType:[HKCorrelationType correlationTypeForIdentifier:HKCorrelationTypeIdentifierBloodPressure] + startDate:[NSDate date] + endDate:[NSDate date] + objects:[NSSet setWithObjects:systolicSample, diastolicSample, nil]]; + + [self verifySample:correlation formatter:nil unit:nil unitStringKeys:@{[HKUnit millimeterOfMercuryUnit]:[[HKUnit millimeterOfMercuryUnit] unitString]} expectedString:@"75 - 120" expectedUnit:[[HKUnit millimeterOfMercuryUnit] unitString]]; + + NSNumberFormatter *formatter = [NSNumberFormatter new]; + formatter.numberStyle = NSNumberFormatterDecimalStyle; + formatter.minimumSignificantDigits = 4; + [self verifySample:correlation formatter:formatter unit:nil unitStringKeys:@{[HKUnit millimeterOfMercuryUnit]:[[HKUnit millimeterOfMercuryUnit] unitString]} expectedString:@"75.00 - 120.0" expectedUnit:[[HKUnit millimeterOfMercuryUnit] unitString]]; + } + + // Test a sample is not in HealthKit + { + HKQuantityType* type = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass]; + HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type + quantity:[HKQuantity quantityWithUnit:[HKUnit gramUnit] doubleValue:2120.0] + startDate:[NSDate date] + endDate:[NSDate date]]; + + [self verifySample:sample formatter:nil unit:[HKUnit gramUnit] unitStringKeys:@{[HKUnit gramUnit]: [[HKUnit gramUnit] unitString]} expectedString:@"" expectedUnit:nil saveToHK:NO]; + } +} + +@end diff --git a/testing/OCKTest/OCKTestUITests/Info.plist b/testing/OCKTest/OCKTestUITests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/testing/OCKTest/OCKTestUITests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/testing/OCKTest/OCKTestUITests/OCKTestUITests.m b/testing/OCKTest/OCKTestUITests/OCKTestUITests.m new file mode 100644 index 000000000..c2f825565 --- /dev/null +++ b/testing/OCKTest/OCKTestUITests/OCKTestUITests.m @@ -0,0 +1,64 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +@interface OCKTestUITests : XCTestCase + +@end + +@implementation OCKTestUITests + +- (void)setUp { + [super setUp]; + + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + self.continueAfterFailure = NO; + // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. + [[[XCUIApplication alloc] init] launch]; + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // Use recording to get started writing UI tests. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +@end