ForYouAndMe
[
](https://cocoapods.org/pods/ForYouAndMe))
[
](https://cocoapods.org/pods/ForYouAndMe))
[
](https://cocoapods.org/pods/ForYouAndMe))
Requirements
iOS 13.0+
Description
The ForYouAndMe
project contains an Example Project
to easily build and run an iOS app that implements the ForYouAndMe
framework. Follow the instructions under Example Project paragraph to build and run it.
The ForYouAndMe
framework is also available as an iOS CocoaPod
library in order to use it in a new project created from scratch. Follow the instructions under Create a study app from scratch paragraph to build and run it.
Example Project
To run the example project:
-
clone the repo.
-
run
pod install
from the Example directory. -
download your Firebase project
GoogleService-Info.plist
from Firebase Console(follow instructions at https://firebase.google.com/docs/cloud-messaging/ios/client#upload_your_apns_authentication_key ) then move it under theExample/ForYouAndMe
folder. -
open
ForYouAndMe.xcworkspace
(not the .xcodeproj file!) with the latest version of XCode. -
in XCode select the
ForYouAndMe
project on the left panel and chooseSigning & Capabilities
tab and enter personal provisioning profile or chooseAutomatically manage signing
and enterTeam
-
On the
Signing & Capabilities
tab also ensure that your app Bundle Identifier matches with the created Firebase app id. -
Navigate - using Finder on Mac, or Windows Explorer on Windows - to
/Example/ForYouAndMe
folder and rename theProjectInfo_sample.plist
toProjectInfo.plist
. -
in XCode open
ProjectInfo.plist
file and fill the property values with the following:-
api_base_url
base url of the server that provides your remote APIs(ex.: https://api.example.com). -
oauth_base_url
base url of the server that handles your Oauth authentication against the supported integrations(ex.: https://oauth.example.com). -
study_id
identifier of your study as recorded on your server as thealias
of your study. -
pin_code_suffix
(only needed in studies that use the pin login) pin code suffix needed for your study, or tonone
if pin code is not supported for your study.
-
-
select the connected iPhone device or a simulator and run the app.
-
in XCode select the
ForYouAndMe
project on the left panel, chooseGeneral
tab and, in theDisplay Name
field enter the app name you want to be displayed on the device.
Create a study app from scratch
The following instructions assume you want to install ForYouAndMe on a brand new project, created using the Storyboard option for the Interface setting and Swift as Language. Of course, this SDK is compatible with other initial settings, but you’ll have to change the project.
Create a new XCode project choosing App
template, then fill the option as follows:
-
Product Name
: name of the study project -
Team
: name of your team defined on the Apple Developer Console -
Organizer Indentifier
: your organisation identifier using the standard formatcom.company
-
Bundle Identifier
: it’s a read only field that shows the bundle id created concatenating theOrganizer Identifier
and theProduct Name
. IMPORTANT: this will be the unique identifier of the new app that will identify it on the App Store. -
Interface
: selectStoryboard
-
Language
: selectSwift
-
Use Core Data
: uncheck it -
Include Tests
: check it
Click on Next
and choose the project location.
ForYouAndMe is available through CocoaPods. To install it follow these steps on terminal
:
-
Install
CocoaPods
following instructions on https://cocoapods.org/ -
Navigate to the project folder and run the command
pod init
A file called Podfile
should have been generated.
3. Open the Podfile
with XCode or another text editor and replace the content with the following lines:
platform :ios, '13.0'
use_frameworks!
# ignore all warnings from all pods
inhibit_all_warnings!
# Pods for project
def available_pods
pod 'ForYouAndMe'
end
target '<project_name>' do
available_pods
use_frameworks!
target '<test_project_name>' do
inherit! :search_paths
# Pods for testing
end
end
Replace <project_name>
with the name you entered on Product Name
on the project creation step.
Replace <test_project_name>
with the test project that has been created, its default name is <project_name>Tests
where the <project_name>
is the Product Name
.
Save the modified file.
4. Run the command
pod install
5. A <project_name>.xcworkspace
file should have been generated under your project folder, open it with XCode.
Once you have installed ForYouAndMe, there are some additional steps to be done in order to configure your own study app:
Capabilities
Add the following Capabilities to your app:
-
Push Notifications
-
Access WiFi Information
Info.plist
Add or edit the following entries to your info.plist file:
-
UIViewControllerBasedStatusBarAppearance
set tofalse
. -
UIUserInterfaceStyle
set toLight
. -
NSAppleMusicUsageDescription
set to$(PRODUCT_NAME) uses Media Library during certain tasks.
-
NSBluetoothAlwaysUsageDescription
set to$(PRODUCT_NAME) uses Bluetooth to connect with wearables.
-
NSBluetoothPeripheralUsageDescription
set to$(PRODUCT_NAME) uses Bluetooth to connect with wearables.
-
NSCalendarsUsageDescription
set to$(PRODUCT_NAME) uses Calendar during certain tasks.
-
NSCameraUsageDescription
set to$(PRODUCT_NAME) captures photos and video during certain tasks.
-
NSContactsUsageDescription
set to$(PRODUCT_NAME) uses Contacts during certain tasks.
-
NSLocationAlwaysAndWhenInUseUsageDescription
set to$(PRODUCT_NAME) will use your location to verify information such as how far you travelled and the speed at which you travelled, as described in the informed consent.
-
NSLocationWhenInUseUsageDescription
set to$(PRODUCT_NAME) will use your location to verify information such as how far you travelled and the speed at which you travelled, as described in the informed consent.
-
NSMicrophoneUsageDescription
set to$(PRODUCT_NAME) records audio during certain tasks.
-
NSMotionUsageDescription
set to$(PRODUCT_NAME) will use your motion data for your active tasks.
-
NSSpeechRecognitionUsageDescription
set to$(PRODUCT_NAME) uses Speech Recognition during certain tasks.
-
LSApplicationQueriesSchemes
set an array of strings, containing:oura
,fitbit
,twitter
,instagram
,gcm-ciq
Below an example of the xml version of the above options:
...
<key>LSApplicationQueriesSchemes</key>
<array>
<string>oura</string>
<string>fitbit</string>
<string>twitter</string>
<string>instagram</string>
<string>gcm-ciq</string>
</array>
<key>NSAppleMusicUsageDescription</key>
<string>$(PRODUCT_NAME) uses Media Library during certain tasks.</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>$(PRODUCT_NAME) uses Bluetooth to connect with wearables.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>$(PRODUCT_NAME) uses Bluetooth to connect with wearables.</string>
<key>NSCalendarsUsageDescription</key>
<string>$(PRODUCT_NAME) uses Calendar during certain tasks.</string>
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) captures photos and video during certain tasks.</string>
<key>NSContactsUsageDescription</key>
<string>$(PRODUCT_NAME) uses Contacts during certain tasks.</string>
<key>NSHealthShareUsageDescription</key>
<string>$(PRODUCT_NAME) will use your health data for further analysis.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>$(PRODUCT_NAME) will use your location to verify information such as how far you travelled and the speed at which you travelled, as described in the informed consent.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>$(PRODUCT_NAME) will use your location to verify information such as how far you travelled and the speed at which you travelled, as described in the informed consent.</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) records audio during certain tasks.</string>
<key>NSMotionUsageDescription</key>
<string>$(PRODUCT_NAME) will use your motion data for your active tasks.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>$(PRODUCT_NAME) uses Speech Recognition during certain tasks.</string>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
...
Cleanup default files and settings
If you have installed ForYouAndMe on a brand new project, there are a few files and settings generated by Xcode (version 12.1 at the time of writing) that have to be fixed:
From the project
-
Remove
Main.storyboard
. -
Remove
SceneDelegate.swift
. -
Remove
ViewController.swift
.
From the info.plist file
Remove the UIApplicationSceneManifest
entry from info.plist
.
In the General Tab
-
Set iOS 13.0 and iPhone .
-
Clear the
Main Interface
field. -
Device Orientation:
Portrait
,Landscape Left
,Landscape Right
.
In the AppDelegate class
-
Remove all methods under the
UISceneSession Lifecycle
mark. -
Add an instance variable called
window
of typeUIWindow?
using:var window: UIWindow?
.
Project Info
Create a plist file called ProjectInfo.plist
and add it to your project. Inside this file, add the following entries:
-
api_base_url
set to the base url of the server that provides your remote APIs. -
oauth_base_url
set to the base url of the server that handles your Oauth authentication against the supported integrations. -
study_id
set to the identifier of your study as recorded on your server. -
pin_code_suffix
set to the pin code suffix needed for your study, or tonone
if pin code is not supported for your study.
How to customise a study app
Firebase
ForYouAndMe uses Firebase platform to track analytics, detect crashes and handle push notifications. Create a project on Firebase and add the resulting GoogleService-info.plist
file to your project.
Then setup your Firebase project to handle push notifications by uploading the APNs Authentication Key
of your app to your Firebase project Settings (see https://firebase.google.com/docs/cloud-messaging/ios/client#upload_your_apns_authentication_key for more details).
Study Video
You have to provide an introduction video for your app. This video format must be mp4
. Name it StudyVideo.mp4
and add it to your project.
Images
ForYouAndMe requires that you provide a specific set of images to your default Assets.xcassets
file. The images needed by the framework fall in two main categories: normal images and template images. While the first ones have no particular requirement, the second ones should be provided in grey scale as they will be used as template images and coloured by the framework according to the color palette of the current study.
Normal images list
image name | description |
---|---|
back_button_primary | Button styled with primary color used for backward navigation typically located on page footers |
camera_switch | Button to switch front and rear camera during some tasks (e.g.: Video Diary) |
checkmark | Generic checkmark icon |
circular | Generic handle used in video player sliders |
clear_button | Clear icon for text fields |
clear_circular | Video player sliders' handle that will be used when the handle is disabled. Typically a transparent will do the trick. |
close_circle_button | Discard button for video diary |
edit | Edit button for text fields |
failure | Generic failure header image |
fitbit_icon | Fitbit device icon |
flash_off | Disabled flash icon for video record |
flash_on | Enabled flash icon for video record |
fyam_logo_generic | Generic logo image that should represent your organization |
fyam_logo_specific | Organization logo image specific of the current study |
health_icon | Health App permission icon |
garmin_icon | Garmin device icon |
instagram_icon | Instagram icon |
location_icon | Location permission icon |
main_logo | Current study logo |
next_button_primary | Button styled with primary color used for forward navigation typically located on page footers |
next_button_secondary_disabled | Button styled with secondary color in disabled mode, used on primary backgrounds |
next_button_secondary | Button styled with secondary color, used on primary backgrounds |
oura_icon | Oura device icon |
push_notification_icon | Push notification permission icon |
rescue_time_icon | Rescue time device icon |
star_empty | Empty rate image shown your data |
star_fill | Filled rate image shown your data |
twitter_icon | Twitter icon |
video_calendar | Calendar icon shown in video diary tasks |
video_pause | Pause button for video players |
video_play | Play button for video players |
video_record | Record button for video players |
video_recorded_feedback | Successful record icon shown in video diary tasks |
video_resume_record | Resume record button for video players |
video_time | Time icon for current record progress in video diary tasks |
Template images list
image name | description |
---|---|
arrow_right | generic disclosure indicator |
back_button_navigation | generic back button used in navigation bars |
checkbox_filled | Generic filled checkbox icon |
checkbox_outline | Generic not filled checkbox icon |
close_button | Close button for modal pages |
contact_icon | Contacts page icon |
devices_icon | Your Apps and Devices page icon |
edit_small | Smaller edit button for text fields |
faq_icon | FAQ page icon |
filter_icon | Filter icon in Your Data |
permission_icon | Permission page icon |
radio_button_filled | Generic filled radio button icon |
radio_button_outline | Generic not filled radio button icon |
review_consent_icon | Review Consent page icon |
rewards_icon | Rewards summary page icon |
tab_feed | Feed tab icon |
tab_study_info | Study Info tab icon |
tab_task | Task tab icon |
tab_user_data | Your Data tab icon |
user_info_icon | Editable profile info page icon |
Framework AppDelegate setup
In your AppDelegate file, import the ForYouAndMe framework by including:
import ForYouAndMe
Add the following delegate method implementation:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return FYAMManager.orientationLock
}
Lastly, in the application(_ application:, didFinishLaunchingWithOptions:)
method delete all existing code and call the startup(withFontStyleMap:, showDefaultUserInfo:, checkResourcesAvailability:, enableLocationServices:)
static method of the FYAMManager
class and store the result in the previously created window
variable.
This method takes three parameters:
-
fontStyleMap
: a dictionary ofFontStyle
->FontStyleData
, whereFontStyle
is an enum representing the palette of font styles used throughout the framework, andFontStyleData
is a struct that allows you to specify custom font, line spacing and uppercase flag for each font style. -
showDefaultUserInfo
: whether or not to show a study-specific page that shows and allows to edit user's personal informations (will be removed in the future in favor of a more dynamic approach). -
appleWatchAlternativeIntegrations
: list of Integrations (e.g.: Garmin, Fitbit, …) which are considered to be mutually exclusive with Apple Watch, regarding the data shown in Your Data. Specifically: if the user, during the Opt-In flow, has agreed to use the Apple Watch (thus she has granted the health permission), only Apple Watch data will be shown in the Your Data page, while all data coming from the integrations listed in this variable will be discarded. If the user has not agreed to use Apple Watch, data coming from Apple Watch will be discarded and all other data will be regularly shown. -
checkResourcesAvailability
: whether or not font styles and images should be validated on startup to ensure that the framework has all the resources it needs. Default: false. -
enableLocationServices
: whether or not to ask user location permission or show the relative permission in the permission page. Default: true. -
healthReadDataTypes
: list of HealthDataType items that should be gathered via HealthKit and sent to the server. Note: this works only if HealthKit has been integrated (see later). Default: empty array.
Example:
var fontStyleMap: FontStyleMap = [:]
if let font = UIFont(name: "Helvetica", size: 24.0) {
fontStyleMap[.title] = FontStyleData(font: font, lineSpacing: 6.0, uppercase: false)
}
if let font = UIFont(name: "Helvetica", size: 20.0) {
fontStyleMap[.header2] = FontStyleData(font: font, lineSpacing: 6.0, uppercase: false)
}
if let font = UIFont(name: "Helvetica", size: 16.0) {
fontStyleMap[.paragraph] = FontStyleData(font: font, lineSpacing: 5.0, uppercase: false)
}
if let font = UIFont(name: "Helvetica", size: 13.0) {
fontStyleMap[.header3] = FontStyleData(font: font, lineSpacing: 3.0, uppercase: false)
}
if let font = UIFont(name: "Helvetica", size: 13.0) {
fontStyleMap[.menu] = FontStyleData(font: font, lineSpacing: 3.0, uppercase: true)
}
self.window = FYAMManager.startup(withFontStyleMap: fontStyleMap,
showDefaultUserInfo: true,
appleWatchAlternativeIntegrations: [.garmin, .fitbit],
checkResourcesAvailability: true,
enableLocationServices: false,
healthReadDataTypes: HealthDataType.allCases)
return true
Below an example of how the AppDelegate
file could looks like after the above steps:
import UIKit
import ForYouAndMe
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
var fontStyleMap: FontStyleMap = [:]
if let font = UIFont(name: "Helvetica", size: 24.0) {
fontStyleMap[.title] = FontStyleData(font: font, lineSpacing: 6.0, uppercase: false)
}
if let font = UIFont(name: "Helvetica", size: 20.0) {
fontStyleMap[.header2] = FontStyleData(font: font, lineSpacing: 6.0, uppercase: false)
}
if let font = UIFont(name: "Helvetica", size: 16.0) {
fontStyleMap[.paragraph] = FontStyleData(font: font, lineSpacing: 5.0, uppercase: false)
}
if let font = UIFont(name: "Helvetica", size: 13.0) {
fontStyleMap[.header3] = FontStyleData(font: font, lineSpacing: 3.0, uppercase: false)
}
if let font = UIFont(name: "Helvetica", size: 13.0) {
fontStyleMap[.menu] = FontStyleData(font: font, lineSpacing: 3.0, uppercase: true)
}
self.window = FYAMManager.startup(withFontStyleMap: fontStyleMap,
showDefaultUserInfo: true,
appleWatchAlternativeIntegrations: [.garmin, .fitbit],
checkResourcesAvailability: true,
healthReadDataTypes: HealthDataType.allCases)
return true
}
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return FYAMManager.orientationLock
}
}
Launch Screen (Optional)
Edit your default LaunchScreen.storyboard
file to show a launch screen that fits your study.
HealthKit (Optional)
Currently data from user’s third party wearables are gathered through server-to-server scheduled operations. However Apple Watch cannot be accessed this way, so the app must take care of gathering data from the Health app and send them to the server.
If you want to include the use of Apple Watch in your study, use the following instructions:
-
Add the following entries to your Info.plist file:
-
NSHealthShareUsageDescription
set to$(PRODUCT_NAME) will use your health data for further analysis
(or something appropriate for your study). -
NSHealthUpdateUsageDescription
set to$(PRODUCT_NAME) will update your health data based on your task results
(actually, what you write here is irrelevant, since the purpose of the HealthKit implementation is just reading Health data. However, you need to add this key because otherwise you’ll get an error while uploading the app to AppStoreConnect, even if official Apple doc states that this description is needed only if you save data in the Health app).
-
-
Add the HealthKit capability to your project.
-
In AppDelegate, inside the
application(_ application:, didFinishLaunchingWithOptions:)
method, provide thehealthReadDataTypes
parameter to thestartup
static method of theFYAMManager
class. As value you’ll need to provide an array of cases of theHealthDataType
enum, thus specifying what data you want to read from the Health app. -
Add the following code at the end of your PodFile:
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
if ['ForYouAndMe'].include? target.name
target.build_configurations.each do |config|
config.build_settings['SWIFT_ACTIVE_COMPILATION_CONDITIONS'] = '$(inherited) HEALTHKIT'
end
end
end
end
Author
LeonardoPasseri, [email protected]
License
ForYouAndMe is available under the MIT license. See the LICENSE file for more info.