I started my Count The Days Left iOS app back in 2015(!), mainly as an exercise to learn the (then) new Swift language, but also to have an app to count down to end of my current contract work!
I’ve made the occasional tweak over the years, but decided it was time it received a bit more love, so I’ve completely rewritten it - even though it basically works in the same way.
For such a simple app, SwiftUI is perfect. I’ve done quite a few SwiftUI projects recently and am happy that the ease of development and increased productivity outweigh the occasional glitches.
I’m not sure the Mac app settings screen is that great though. For SwiftUI to be truly great for cross-platform work, it’s on the Mac that is by far the most problematic. If I have the energy I may go back and try to improve that.
I think the app’s UIis so much better now. It was a lot easier to add a nice animation on the progress view - take a look at this preview video to see what I mean …
WatchOS now supports iCloud Key-Value store sync
The app uses both UserDefaults and iCloud key-value store to store the user’s settings. The latter is used so you can sync your settings across devices.
Previously, pushing the settings to the watch meant some complicated logic in manually pushing the settings across from the phone every time they changed, which was problematic and a bit unreliable.
Now in watchOS 9.0, the watch also supports iCloud Key-Value store sync, which made the code MUCH simpler as it can now reuse the data management code from the main app.
This has meant that the watch app now has a minimum OS version of 9.0+, but again I think the trade off of much increased reliability is worth it.
New features
I’ve completely rewritten the widget code, and also added some nice lock screen widgets for iOS 16 users.
Moving to watchOS 9.0 also means I can reuse the widget code to improve the watch complications.
The Siri shortcuts code is much improved too - moving to the new AppIntents framework and SwiftUI for the visual component.
I’m also using the new shortcut provider API to suggest an appropriate shortcut to access your days left data directly in the Shortcuts app.
Modernised Swift code
It’s probably to be expected, but some of the 7 year old code was VERY out of date, and a little embarrasing 😳
I’ve restructured so it’s much better organised, uses protocols and generics where appropriate, and is a much better showcase for what I can do (I hope!)
Accessibility Improvements
Using SwiftUI means the accessibilty features are generally better straight out of the box, but I have spent some time making sure that voice over works well, as well as making the UI scalable using differemnt font sizes.
Removed some legacy extensions
The old school Today widget has gone, as has the iMessage extension - that seemed a good idea at the time but they really haven’t take off (to say the least!)
I’ve also removed the “tip” option, where people could do an in-app purchase to say thanks. TBH so few people were using it - and I definitely wasn’t promoting it in any way! - that I couldn’t be bothered to spend the effort porting the code.
Summary
I’m really happy with the updated code, and I’ll be much happier in potential customers looking at it as an example of my work.
If you want to take a look yourself, it’s here on GitHub
iOS 16 should be available any day soon now, so I’ve been adding some new features to the Yeltzland app to take advantage.
Lock Screen widgets
The biggest visible change in iOS 16 are the new lock screen widgets - which presumably will be great with the heaviliy rumoured always-on screens of the new phones.
The widgets show either the latest score, the last result or the next upcoming fixture, whatever is the most relevant at the current time.
The app already had Apple Watch complications, which made it very little work to add similar widgets on the lock screen.
It took a bit of fiddling to get the update frequency working correctly, especially during the match. This works quite well now, especially if you have the game time tweet notifications feature turned on (which I can use to trigger an widget update out of the scheduled timeline)
As you can see from the screenshot above, I’ve also added a new “badge only” widget, which just shows the club badge if you just want to personalise your phone a bit.
Improved complications on the Apple Watch
Watch complications and lock screen widget code has been unified, so I’ve been able to combine the code for both into a single extension.
This also means the watch complications are a bit better now, as they benefit from the work I put in to keep them better updated as the goals fly in.
Better Siri Shortcuts
Thankfully the old intent definition code has been deprecated into a much nicer system using AppIntents. This makes it much nicer to both define and build the logic for Shortcuts support, as well as to be able to donate shortcut suggestions directly from the app.
This means I have been able to delete a whole load of code - which is always nice - and simplify the discovery of the shortcuts the app supports.
There’s how I use the shortcuts (so I can ask Siri the latest score) …
… plus how it looks visually when this shortcut is run
Summary
It’s been the quietest summer for a while on the new feature front, with not many customer facing changes of note in iOS 16.
However, I think the lock screen widgets are a big improvement, and I’m pretty happy how they’ve turned out.
Let’s see if we have any surprises later today when the new hardware is announced 🤞
I’ve had a bit of down time recently - which has been great - and in-between watching the Euros and the Tour de France, I’ve had time to watch quite a few WWDC videos.
One video entitled Showcase app data in Spotlight looked interesting, as I’d never considered adding anything from any of my apps into Spotlight Search.
Now the video itself wasn’t massively useful for me, as it was most about how you can feed Core Data easily into Spotlight - and I don’t really use Core Data unless I absolutely have to!
However, it inspired me to get the fixture and results data from my Yeltzland app into Spotlight.
Adding entries into Spotlight
The logic of my code is as follows:
Listen for updates to the fixtures data
On update, first remove all entries for the fixture data domain identifier (a unique string denoting the set of entries)
Then add a new index entry for each match in the data set
The full code is available on GitHub and should be pretty self-explanatory.
To remove all entries for a domain identifer, simply call:
Then the code to add an individual entry to the search index is straightforward too:
var items: [CSSearchableItem] = []
// Fetch all fixtures
let fixtures = FixtureManager.shared.allMatches
for fixture in fixtures {
// Create an attribute set to describe the fixture
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeData as String)
attributeSet.title = fixture.spotlightSearchTitle
attributeSet.contentDescription = fixture.spotlightSearchDescription
// Create an item with a unique identifier, a domain identifier, and the attribute set you created earlier.
let item = CSSearchableItem(uniqueIdentifier: "\(SpotlightManager.domainIdentifier)-\(fixture.identifier)",
domainIdentifier: SpotlightManager.domainIdentifier,
attributeSet: attributeSet)
items.append(item)
}
CSSearchableIndex.default().indexSearchableItems(items) { error in
if let error = error {
print("Error add spotlight entries: ", error.localizedDescription)
} else {
print("Spotlight entries successfully added")
}
}
How it looks
That was all very simple, and you can see in the screenshot below it came out very nicely
If I’d have know it was that easy (and how to do it!), I would have added this years ago 😀
Annual list of things if announced next week would make me very happy
It’s that time of year again when Apple presents what exciting new features iOS developers are going to be integrating into their apps over the summer.
I’m surprisingly excited about WWDC 2021, and as per tradition here’s my top 5 list of what I’d love to see announced.
1. iPadOS multi-tasking improvements
Once again iPadOS is falling behind, both in parity with iOS14 features, and allowing users take full advantage of the fantastic hardware power of modern iPads.
Other than just catching up e.g. allowing widgets be placed anywhere on the home screens rather than in a single column, we really need a complete redesign of the almost unusable multi-tasking setup.
It’s clear iPadOS needs to be closer to MacOS in offering a better way to run multiple apps at once, run background services, and other “power user” features. Despite the name of this blog, it’s now pretty rare I do any work on my iPad ☹️
Not holding my breath on getting fundamental improvements this year, but surely Apple must be completely rethinking how multi-tasking works? Why else would they break out the iPadOS name other than to make a significant break from iOS?
2. SwiftUI improvements
I really love SwiftUI, both the simplicity of building nice interfaces in code, plus the functional/reactive way it works.
However we really need the platform to become more mature this year. There are so many small but significant pieces missing, that often mean writing UIKit wrappers to achieve what should be built-in features.
Off the top of my head, things that have been painful for me recently include:
Text rendering - in particular using attributed text
Pull to refresh
Navigation - the current use of NavigationLink doesn’t scale at all well for more complex apps
3. More support for Combine
I’ve started using and learning more about Combine recently, and really like it. It obviously works really well in conjunction with SwiftUI, and can simplify many common patterns of app development.
However, it would be great if there were more built-in Publishers for other parts of the system. Casey Liss wrote a great article summarising his thoughts on this topic, and I couldn’t agree more.
With the forthcoming async/await support in Swift 5.5 - and having used this pattern in Flutter recently, I can’t wait for this - it will be interesting to see if Combine is continued to be extended by Apple, or if it becomes semi-abandoned in favour of newer technologies. I really hope not!
4. Interactive widgets
A no brainer this one. Widgets are great, and I use them extensively on both my iPhone and iPad.
Like everyone, I probably “over widgeted” my home screens when they first came out, but now have a good mix of useful widgets amongst my app icons.
However it seems obvious that adding some limited interactivity would make them even more useful. The common example given is play/pause buttons for audio widgets, and I can’t believe they won’t be implementable after this year’s OS updates.
5. Core Data replacement
We really need a replacement for Code Data for the modern age.
So many apps I work on follow a similar pattern - they interact with a server API that returns JSON data, tand we to cache on device for use when the user if offline.
On a recent project we used Realm for the local database storage. It wasn’t too bad compared with past experiences with Core Data, but we still ended up writing too much bolierplate code to manipulate the data from the API response into the correct types to allow it to be easily saved and retrieved offline.
Drew McCormack wrote a great article a few days ago about what he calls “SwiftData” - and I really recommend you reading it if you haven’t already.
I’m not sure about his thoughts on supporting decentralised databases, but having a simple database system that easily maps to say Codable structs, is extensible by default, and “just works” would be fantastic.
TBH I’m not holding out much hope for this, but any improvements to CoreData to match actual usage patterns I see in most apps would be very welcome.
Summary
I’ll update the scorecard after all the details are out of WWDC 2021, but I really hope at least 3/5 come true - and we get some exciting (not AR/VR!) new things to play with that I didn’t realise I needed!
After a year of working on a large Flutter project, plus working on a much smaller React Native project recently, it seems like a good time to update my thoughts on cross-platform development options in 2021.
Flutter
I’ve just completed a year long project for a large client helping rewrite their mobile apps in Flutter.
Neither I or the other members of the team had done much/any Flutter development before, so it meant learning best practices together - sometimes through trial and error, finding out what worked for our particular app.
I really enjoyed using Flutter, and it’s definitely the nicest cross-platform development system I’ve used so far.
Good Points
Uses a declarative UI (like SwiftUI) which is a productive, modern way of developing reliable and predictable user interfaces
Hot reload - not needing to recomplie to see every change in the simulator - is very nice when doing UI work
Visual Studio Code is a great and versatile development tool, with lots of handy extensions (I’d strongly recommend using it rather than Android Studio for doing Flutter development)
Less Good Points
Support for packages can be a little patchy
Flutter has support for most common requirements out of the box, or with Google written packages.
However for more specialised needs, several 3rd party packages we used weren’t of great quality, and we had to fix some fairly basic bugs in them. They were mostly packages developed by a single developer, and the owner generally didn’t have the time or inclination to keep them up-to-date or fix every bug found.
As ever with depending on 3rd party packages, use at your own risk
Using Dart was fine, but felt a bit limited compared to using Swift
React Native
I picked up a small React Native project for a new client, who wanted a few updates made to an existing app another agency had developed for them.
I was looking forward to using React Native, as I’d only briefly looked at it before - and to be fair haven’t spent enough using it to make a definitive judgement - but to be honest I was quite disappointed.
The app was using Expo, which offers a slightly clunky hot reload experience.
I also didn’t really enjoy going back to using JavaScript for mobile development, after using more suitable strongly typed and compiled languages.
I’ll hold judgement until I’ve done more RN coding (and it may be that the inherited codebase wasn’t well designed in the first place), but my first commercial experience of it wasn’t anywhere near as nice as developing in Flutter.
Summary
I’d definitely recommend using Flutter for the right projects. Those projects that are mostly cross-platform rich UIs without any complex on-device requirements are a good fit, as you are less likely to hit any issues with pany 3rd party ackages you need.
I can see how React Native might be a good fit for a team that already uses React in a web app, but unless that is you - or your team has strong front-end JavaScript skills already - I can’t see much advantage in using it.
3 years ago I mentioned using Xamarin and Cordova/Ionic, and I definitely wouldn’t recommend starting any new project using them any more.
However, I’ve started a a new project back using Swift/SwiftUI/native iOS development - and am VERY happy doing just that! SwiftUI in particular is a joy to use, and I am much more productive using it - even compared to doing Flutter development with it’s useful hot reload.