{"id":20740081,"url":"https://github.com/rcasanovan/ihealth","last_synced_at":"2025-04-24T02:24:54.228Z","repository":{"id":243133251,"uuid":"166024839","full_name":"rcasanovan/iHealth","owner":"rcasanovan","description":"A simple iOS app to integrate HealthKit to show some info for the user","archived":false,"fork":false,"pushed_at":"2019-02-12T20:09:44.000Z","size":31220,"stargazers_count":8,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-30T06:04:23.818Z","etag":null,"topics":["cocoapods","codable","decodable","healthkit","json","protocol","realm","realm-database","swift","viper","viper-architecture","viper-pattern-architecture"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rcasanovan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-01-16T10:57:00.000Z","updated_at":"2024-10-08T20:56:24.000Z","dependencies_parsed_at":"2024-06-06T22:55:16.169Z","dependency_job_id":null,"html_url":"https://github.com/rcasanovan/iHealth","commit_stats":null,"previous_names":["rcasanovan/ihealth"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcasanovan%2FiHealth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcasanovan%2FiHealth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcasanovan%2FiHealth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcasanovan%2FiHealth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rcasanovan","download_url":"https://codeload.github.com/rcasanovan/iHealth/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250546833,"owners_count":21448404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cocoapods","codable","decodable","healthkit","json","protocol","realm","realm-database","swift","viper","viper-architecture","viper-pattern-architecture"],"created_at":"2024-11-17T06:27:20.857Z","updated_at":"2025-04-24T02:24:54.208Z","avatar_url":"https://github.com/rcasanovan.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# iHealth\n\nThis is a simple iOS app to integrate HealthKit to show some info for the user\n\n## 🚨 Important note 🚨\n\nThis project is using cocoapods. Please be sure to run the **pod install** command before running the project.\n\nIf you have any doubt about cocoapods you can check the reference [here](https://cocoapods.org).\n\n## Cool things with the demo\n\n* No internet connection message: If the user opens the app and it doesn't download the goals list before, no internet connection message appears (the app needs the goals information in order to determinate the user progress)\n* Local goals cache: The app is using a local goals cache so if the device doesn't have internet connection, the app will use the local information\n* Share option: You can share a screenshot for your daily progress\n\n## Project Architecture \n![alt tag](https://github.com/rcasanovan/iHealth/blob/master/Images/projectArchitecture.jpeg?raw=true)\n\nReferences:\n* [Viper architecture](https://www.objc.io/issues/13-architecture/viper/)\n* [Viper for iOS](https://medium.com/@smalam119/viper-design-pattern-for-ios-application-development-7a9703902af6)\n\n## How did I implement VIPER?\n\nBasically I have a protocol file for each scene in the app. This file defines the interaction between each layer as following:\n\n* View - Presenter: protocols to notify changes and to inject information to the UI.\n* Presenter - Interactor: protocols to request / receive information to / from the interactor.\n* Presenter - Router: protocol to define the transitions between scenes (I skiped this protocols for the demo because I have only a scene there).\n\nWhith this protocols file is really easy to know how each layer notify / request / information to the other ones so we don't have any other way to communicate all the layers.\n\nAnother important point is because I'm using protocols it's really easy to define mocks views / presenters / interactors / routers for testing.\n\n```swift\n// View / Presenter\nprotocol GoalsViewInjection : class {\n    func showProgress(_ show: Bool, status: String)\n    func showProgress(_ show: Bool)\n    func showMessageWith(title: String, message: String, actionTitle: String)\n    func loadGoals(_ viewModels: [GoalViewModel])\n}\n\nprotocol GoalsPresenterDelegate : class {\n    func viewDidLoad()\n    func refresh()\n}\n\n// Presenter / Interactor\n\ntypealias GoalsGetGoalsCompletionBlock = (_ viewModel: [GoalViewModel]?, _ success: Bool, _ error: ResultError?) -\u003e Void\n\nprotocol GoalsInteractorDelegate : class {\n    func getGoalsList(completion: @escaping GoalsGetGoalsCompletionBlock)\n    func clear()\n}\n```\n\n## First at all. Where is the data came from?\n\nI'm using the following endpoint to get the goals list -\u003e https://thebigachallenge.appspot.com/_ah/api/myApi/v1/goals/.\n\n## Data models\n\n### Network data models\n\n```swift\npublic struct GoalsResponse: Decodable {\n    \n    let items: [GoalResponse]\n    \n}\n\npublic struct GoalResponse: Decodable {\n    \n    let id: String\n    let title: String\n    let description: String\n    let type: String\n    let goal: Int\n    let reward: RewardResponse\n    \n}\n\npublic struct RewardResponse: Decodable {\n    \n    let trophy: String\n    let points: Int\n    \n}\n```\n\nI'm using a Swift Standard Library decodable functionality in order to manage a type that can decode itself from an external representation (I really ❤ this from Swift).\n\nReference: [Apple documentation](https://developer.apple.com/documentation/swift/swift_standard_library/encoding_decoding_and_serialization)\n\n### Local goals data model\n\nThis model is used for the local goals\n\n```swift\nclass LocalGoal: Object {\n    \n    @objc dynamic var goalId: String?\n    @objc dynamic var title: String = \"\"\n    @objc dynamic var goalDescription: String = \"\"\n    @objc dynamic var type: String = \"\"\n    @objc dynamic var goal: Int = 0\n    @objc dynamic var trophy: String = \"\"\n    @objc dynamic var points: Int = 0\n    \n    override class func primaryKey() -\u003e String? {\n        return \"goalId\"\n    }\n    \n}\n```\n\nAs I'm using Realm for this it's important to define a class to manage each model in the database. In this case we only have one model (LocalGoal)\n\nReference: [Realm](https://realm.io/docs/swift/latest)\n\n## Managers\n\nI think using managers is a good idea but be careful!. Please don't create managers as if the world were going to end tomorrow.\n\nI'm using only 4 here:\n\n### ShareManager\n\nUsed to share the current progress using UIActivityViewController.\n\n### ReachabilityManager\n\nUsed to manage the reachability. In this case I would like to notify a little issue related with the simulator. *It seems Xcode has an issue with the simulator because if you try to turn off the wifi and turning on again, the observer for the state change is not triggering. It's working 100% fine in a real device*.\n\n### LocalGoalManager\n\nUsed to save the goals locally using a Realm database.\n\n### HealthManager\n\nUsed to manage all the connections and requests with the HealthKit framework.\n\n## How it looks like?\n\n### General goals and my personal goals\n![alt tag](https://github.com/rcasanovan/iHealth/blob/master/Images/01.PNG?raw=true)\n![alt tag](https://github.com/rcasanovan/iHealth/blob/master/Images/02.PNG?raw=true)\n\n### Share option \u0026\u0026 permission request\n![alt tag](https://github.com/rcasanovan/iHealth/blob/master/Images/03.PNG?raw=true)\n![alt tag](https://github.com/rcasanovan/iHealth/blob/master/Images/04.PNG?raw=true)\n\n### No internet connection screen\n![alt tag](https://github.com/rcasanovan/iHealth/blob/master/Images/05.PNG?raw=true)\n\n## What's left in the demo?\n\n* Realm migration process: It would be nice to add a process to migrate the realm database to a new model (just in case you need to add a new field into the database).\n* Localizable strings from server (goals list): It would be nice to have an option to retrieve the goals list with localizable strings according with the device language.\n* Logic to refresh my goals screen every xx minutes: It's a good idea to have a logic to refresh my goals screen every xx minutes.\n\n## Programming languages \u0026\u0026 Development tools\n\n* Swift 4.2\n* Xcode 10.1\n* [Cocoapods](https://cocoapods.org) 1.5.3\n* Minimun iOS version: 12.1\n\n## Third-Party Libraries\n\n* [RealmSwift](https://github.com/realm/realm-cocoa) (3.7.6): A mobile database that runs directly inside phones, tablets or wearables\n* [SVProgressHUD](https://github.com/SVProgressHUD/SVProgressHUD) (2.2.5): A clean and lightweight progress HUD for your iOS and tvOS app.\n* [XYPieChart](https://github.com/xyfeng/XYPieChart) (0.2): A library to create pie charts for iOS and MacOS.\n\n## Support \u0026\u0026 contact\n\n### Email\n\nYou can contact me using my email: ricardo.casanova@outlook.com\n\n### Twitter\n\nFollow me [@rcasanovan](http://twitter.com/rcasanovan) on twitter.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frcasanovan%2Fihealth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frcasanovan%2Fihealth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frcasanovan%2Fihealth/lists"}