Streaks Feature, Updated Widgets and Core Data

Tuesday, 18 April, 2023

I just pushed a Zenitizer update to TestFlight earlier today which includes a brand-new feature that I hope to be a great source of motivation for your regular meditation practice: “Meditation Streaks”

Each day you hit your meditation goal, your streak grows. In order to keep your streak, it is sufficient to simply meditate as little as one minute a day - even if this is below your goal. While this will not increase your streak it will prevent breaking the streak. Only if you do not meditate at all on a given day the streak will be reset to 0.

With this behaviour, I was hoping to find a good compromise between motivating you to build a regular practice but without putting too much “pressure” on “achieving goals” (mindfulness meditation should be calming and not adding more stresses to your life, after all 🧘).

I’d love to know what you think about this approach and how the feature works for you personally, so please don’t hesitate to reach out and let me know!

A composition showing screenshots of the new streaks feature on both Apple Watch and iPhone.

New Streak View + Updated Widgets & Complications

The screenshot above shows the new UI elements for displaying streak progress in various forms and contexts. The “week view” is a custom SwiftUI view that can (and will in a future update) be extended to show larger time spans (e.g. one month at a time). This will allow revisiting the meditation history laid out like a calendar.

Design Considerations

I wanted the StreakView to have a “call for action” title like “Grow your 42 Day Streak” or “Keep Your 42 Day Streak” (unless you already reached your daily meditation goal). The week view primarily serves to see at a glance how you’ve been doing this week (+ may allow revisiting previous days’ meditation history details in the future) and there’s a small indicator of your personal record to date.

After a couple of design iterations I’m pretty happy with the result but I’m sure I’ll make tons of tweaks before Zenitizer makes it to the App Store 🙈 Please let me know if you have any suggestions or questions about the feature as well as the design!

Under The Hood & New Learnings (Core Data)

The majority of the work, however, was focussed on what is not visible: the underlying data and persistence layers! So far, all of Zenitizer’s persistence needs were covered by NSUserDefaults as all the meditation history itself was exclusively written to and read from Apple Health.

Now in order to properly support streaks and efficiently query meditation history and streak data I needed my own on-device persistence solution and after a bit of research I decided to go with Core Data.

You can tell that the framework has its roots in the “Objective-C days” and I personally prefer Swift structs and other value types as well as Swift’s strict handling of Optionals in favour fetching and passing around NSManagedObject references because the former will often force you to address issues at compile time instead of (hard to find?) runtime issues you may get with NSManagedObjects and NSFetchRequests… In the end of the day though, each framework, tool or solution has its pros and cons and, all things considered, CoreData is working really well for me and I am definitely starting to embrace it… 🤓

Donny Wals’ book Practical Core Data was a fantastic resource on my journey to familiarize myself with Core Data. I bought it quite a while ago and it was just sitting in my Gumroad library because I never got around to reading it… Finally, I was forced to work my way through it and it has really helped a lot!

In addition, I would also highly recommend this Apple developer video to anyone getting started with Core Data in modern apps!

Topics

If you enjoyed this post, check out the topics below to find similar ones: