iOS 13 Steps+ release
September 27, 2019
It was late, but I finally released my iOS 13 release (🎉) for Steps+.
There isn't too much to report, but there were some interesting things - for one I was forced finally to upgrade from the old
Since Steps+ has supported theming before most (all?) pedometer applications, it already has a pretty robust theming system. The struggle that I had, was adapting the new Dark Mode "API"s into my system. For the lifetime of Steps+, in which it has supported theming, it has relied on notifications; however the trait mode changed API was localized to UI components and doesn't have a notification when it changed (as far as I could tell, I researched but could have been wrong!).
In order to tell my theming engine that it needed to use the dark theme or the "default", light mode - I needed to generate my own notification.
Of course, this is kind of going around how Apple wants you to do this - so take this "hack" with a grain of salt and it might not be what you want to do in your application unless you think it is the correct tradeoff for you, your app, and your situation.
After all, what is software development but making tradeoffs of this sort?
Since the method I needed to override was on
Anyway, I decided to make a custom
I am not entirely sure this is terrible practice - but it is certainly not the ideal way to do this if you are making a new application!
As a final aside - I want to make a bigger point here. What I've presented in this blog is not a great practice; that's OK. Taking tech debt like this is better than not being able to ship. Sometimes you make these gambles and they do not pay off at all, but sometimes they do! The main thing I want to impart is that you do not always need to ship the best code - you just need to ship a good product.
There isn't too much to report, but there were some interesting things - for one I was forced finally to upgrade from the old
UIAlertView
. I knew one of these days I was going to have to do so, and I finally removed the last from the app (glad to get rid of those pesky depracation warnings). Since Steps+ isn't my full time gig - I have to be very selective about what I work on with it, and what technical debt is the most pressing. I finally was taken to technical collections, but it wasn't too painful to pay that specific one off, maybe a day of work. Since Steps+ has supported theming before most (all?) pedometer applications, it already has a pretty robust theming system. The struggle that I had, was adapting the new Dark Mode "API"s into my system. For the lifetime of Steps+, in which it has supported theming, it has relied on notifications; however the trait mode changed API was localized to UI components and doesn't have a notification when it changed (as far as I could tell, I researched but could have been wrong!).
In order to tell my theming engine that it needed to use the dark theme or the "default", light mode - I needed to generate my own notification.
Of course, this is kind of going around how Apple wants you to do this - so take this "hack" with a grain of salt and it might not be what you want to do in your application unless you think it is the correct tradeoff for you, your app, and your situation.
After all, what is software development but making tradeoffs of this sort?
Since the method I needed to override was on
UITraitEnvironment
- and after some thought the singular place that must conform to this (but not just be a random View Controller that I assume is always in memory) is the application's window! The way Window's are treated and are considered was changed with iOS 13 - but mostly for iPad; and Steps+ is iPhone only. I will likely pay for this technical debt around iOS 18. Anyway, I decided to make a custom
UIWindow
subclass (seriously!). This will let me get those calls and turn them into notifications for my theming engine to detect the current interface style and use the current theme. When this is my main window, it gets all the call backs that I need to fire my notification.
import Foundation
@objc final class KAWindow: UIWindow {
@objc static let TraitThemeCollecitonNotification: NSNotification.Name =
NSNotification.Name(rawValue: "KATraitThemeCollecitonNotification")
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard let previousTraitCollection = previousTraitCollection else {
return
}
if #available(iOS 13.0, *) {
if previousTraitCollection.userInterfaceStyle != UITraitCollection.current.userInterfaceStyle {
NotificationCenter.default.post(name: KAWindow.TraitThemeCollecitonNotification, object: nil)
}
}
}
}
I am not entirely sure this is terrible practice - but it is certainly not the ideal way to do this if you are making a new application!
As a final aside - I want to make a bigger point here. What I've presented in this blog is not a great practice; that's OK. Taking tech debt like this is better than not being able to ship. Sometimes you make these gambles and they do not pay off at all, but sometimes they do! The main thing I want to impart is that you do not always need to ship the best code - you just need to ship a good product.