Beiwe is a smartphone-based digital phenotyping research platform. This is the Beiwe iOS app code. The Beiwe2 app is also available on the Apple app store to use with open source builds of the Beiwe backend.
Due to the persistence work and its reliance on GPS, battery drain suddenly becomes a big concern especially if this has impacts on participants leaving studies. Fortunately - though I'm currently bafflingly 100% stuck on it - there is a feature added in iOS 17 called a Background Health Research Task (technically BGHealthResearchTask) that I am working on. This should allow full, or at least very good, background app persistence without requiring your phone's GPS sensor be enabled.
A secondary but still critical part of this work has been a huge push on squashing bugs, particularly due to threading. Some of this was backported onto 2.4.x branch (you may have noticed that it is all the way up to 14).
PromiseKit
For the 2.5 release of Beiwe, as a substantial developer-facing push, I have removed the use of PromiseKit from codebase. Developers interested in that process, as it resulted in a huge amount of code churn, can find the commits with this command:
git log --no-color --grep '\[purge-promisekit\]' This work occurred, based on the commit dates, February 6-14.
PromiseKit was not competently used in this project. I'm sure there are nice uses of this Promise-style pattern (no I don't, I'm lying, my entire view of that has been irrecoverably poisoned) but Beiwe-iOS was not that use case. This library made code unreadable, hid threading and thus caused race conditions, obfuscated everything everywhere causing and then swallowing errors, and made writing code as simple as launching the app potentially unsafe operations because operations were untracked and could happen in any order. PromiseKit was adopted very early on in development of the app, and then patchily addited to over time. Some of which was my own fault, and a skill and knowledge issue as I took over as primary developer in this codebase over the past couple years.
All PromiseKit usage has been removed and the library itself has been removed.
All network code (which uses AlamoFire) has been entirely rewritten. We can now inspect the returns of http error codes and message bodies in their correct context, and AlamoFire features are now exposed to the rest of the app. At no time in the development history of this app should that have been allowed.
File IO no longer hides order of operations inside promises. 🙄 This directly resulted in a followup rewrite of file io to fix a longstanding data corruption issue.
App load is no longer asynchronous - this required stupid hacks to wait for sections of the codebase to be ready, a process which is trivially deterministic if you don't use promises - and it is now WAY faster. There is still some low-priority cleanup to be done here.
Accessing the database can no longer crash the entire app due to multithreading issues that simply were not handled at all 🙄.
A bug in ObjectMapper that can cause crashes, thought to be a database error because it occurred in a very similar pattern, is now exposed for what it is. I can now move on to working out a fix. Maybe. It's a tough one (After the file io rewrite mentioned above this is the only remaining crash that is reported by the app to our error reporting service.)
Overall code smell has been improved. I will admit that some of the http code is much more verbose, but I would argue that the fundamentals it can now address substantially outweigh its previous simplicity.
Our ability to reason about behavior of the app without saying "well it's wrapped in a Promise chain and running asynchronously and is confusing" is... well it exists now and I think that's pretty cool.
File Corruption
This has been a real thorn in the side of the iOS app. The reasons this occurred were (inevitably) related to threading and PromiseKit, and the tale of the changes the code went through as various fixes were applied are truly tedious. Mostly, the (insane) hoops we were jumping through previously to recover as much as was possible occurred on the server. If you want to follow that you can follow the issue on the beiwe-backend codebase here https://github.com/onnela-lab/beiwe-backend/issues/360.
(I failed to create issues for some of this work, I apologize for that, hopefully this is enough.)
Substantial Improvement of Background App Persistence.
This is our big ticket item, you can track part of it over on https://github.com/onnela-lab/beiwe-ios/issues/54. If you would like to be a beta tester just ask.
Due to the persistence work and its reliance on GPS, battery drain suddenly becomes a big concern especially if this has impacts on participants leaving studies. Fortunately - though I'm currently bafflingly 100% stuck on it - there is a feature added in iOS 17 called a Background Health Research Task (technically
BGHealthResearchTask
) that I am working on. This should allow full, or at least very good, background app persistence without requiring your phone's GPS sensor be enabled.A secondary but still critical part of this work has been a huge push on squashing bugs, particularly due to threading. Some of this was backported onto 2.4.x branch (you may have noticed that it is all the way up to 14).
PromiseKit
For the 2.5 release of Beiwe, as a substantial developer-facing push, I have removed the use of PromiseKit from codebase. Developers interested in that process, as it resulted in a huge amount of code churn, can find the commits with this command:
git log --no-color --grep '\[purge-promisekit\]'
This work occurred, based on the commit dates, February 6-14.PromiseKit was not competently used in this project. I'm sure there are nice uses of this Promise-style pattern (no I don't, I'm lying, my entire view of that has been irrecoverably poisoned) but Beiwe-iOS was not that use case. This library made code unreadable, hid threading and thus caused race conditions, obfuscated everything everywhere causing and then swallowing errors, and made writing code as simple as launching the app potentially unsafe operations because operations were untracked and could happen in any order. PromiseKit was adopted very early on in development of the app, and then patchily addited to over time. Some of which was my own fault, and a skill and knowledge issue as I took over as primary developer in this codebase over the past couple years.
All PromiseKit usage has been removed and the library itself has been removed.
File Corruption
This has been a real thorn in the side of the iOS app. The reasons this occurred were (inevitably) related to threading and PromiseKit, and the tale of the changes the code went through as various fixes were applied are truly tedious. Mostly, the (insane) hoops we were jumping through previously to recover as much as was possible occurred on the server. If you want to follow that you can follow the issue on the beiwe-backend codebase here https://github.com/onnela-lab/beiwe-backend/issues/360.
Remaining Issues