Software Engineer at Capital One UK
Aberystwyth
I’ve just been to iOSDevUK 9, one of the most anticipated annually-held iOS conferences. This year, it was held on the 2nd to 5th of September at its traditional venue of Aberystwyth University in Wales. iOS developers from all over the world go to this event, and this year was no exception. I was fortunate enough to attend the conference this year along with my colleagues from Capital One UK (one of the conference’s main sponsors.) There were lots of great things I can talk about, the people I’ve met, the sessions, the venue, and so forth. However, this blog post will focus on the technical stuff I’ve learned from the talks at the conference.
I thought I would pack everything into one post, but there were so many things going on. SwiftUI stuff could easily dominate this post. So I split this into multiple posts, a series if you like. The series will start off with SwiftUI. And I’m also writing up about talks related to accessibility in iOS development. So that one will surely be the next part.
There were lots of talks about SwiftUI. There was at least one session/talk about SwiftUI on every single day. And I really enjoyed them! I knew there would be loads of talks about SwiftUI, so I had a play with it before going to the conference, and it really paid off.
The SwiftUI journey started on Monday(2nd September) evening with Paul Hudson SwiftUI workshop. We were creating a simple food ordering app. Paul provided a starting point project and a document with some instructions to follow. He really got our hands dirty with SwiftUI and its basics views like Lists
, Stacks
, Navigation Views
, all the way to more advanced things like EnvironmentObject
, ObservableObject
, and State
.
The workshop was just an hour and a half, but it was amazing that we could get a demonstrable food ordering app with a menu list screen, menu detail screens, and a place order screen done in such a short time with SwiftUI.
You can check out the code for this project on this GitHub page. And I highly recommend checking out Paul Hudson’s SwiftUI by example. It’s straightforward, and it’s what I used to prepare my SwiftUI knowledge for this conference.
Despite not having “SwiftUI” in the name of his talk, this talk is a showcase of how to how to utilise SwiftUI reusability for the UIs of a cross-platform(iOS, iPadOS, MacOS, TvOS) project.
Jan talked about the real-world situation of how varied the design of screens of the same app on different platforms are, and how SwiftUI can save us time from creating and maintaining those screens. SwiftUI can adapt the UIs to fit the design language on different platforms only to some extent. There still some work for developers to do. Every app and design is not going to look exactly the same on each platform. The layout of your app on macOS could look different from what SwiftUI thinks it could be based on the SwiftUI class for iOS. You may need to rewrite the SwiftUI class for the same screen on the other platform. However, you can ease the styling process by using SwiftUI ViewModifier to create custom styles and reuse them on all platform screens.
Instead of “Write once, run everywhere”, SwiftUI allows us to “Learn once, apply everywhere”.
Here is an example of how easy it is to create a custom SwiftUI ViewModifier of an app theme and then apply that to where ever we want. The code goes something like this
struct PositiveButtonMod: ViewModifier {
func body(content: Content) -> some View {
content
.font(.largeTitle)
.padding(.horizontal, 8)
.padding(.vertical, 6)
.opacity(0.8)
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(5)
}
}
Here is our complicated positive button modifier. It has many attributes. However, this is the only place where the code for positive button style lives. We can reuse it anywhere in the project.
struct ContentView: View {
var body: some View {
Button(action: accept) {
Text("Accept")
}.modifier(PositiveButtonMod())
}
func accept() {
// perform accept action
}
}
We only have to write one line instead of seven for the styling of this button (and the next positive buttons.) We have achieved reusability as well as simplicity and maintainability. If the design team decided to change the background colour of positive buttons from blue to yellow for some reason, we only needed to change it once.
Daniel’s hilarious and fascinating talk gave a lot of folks in the room better understanding of how powerful yet simple SwiftUI is. The highlight for me was Property Wrappers. He showed how to use some basics ones like State
, and Binding
. But what I want to talk about here is how to create custom property wrappers. The goal is quite similar to custom ViewModifiers, simplicity and reusability.
A little bit about what Property Wrappers is. It’s a way of abstracting logic for a property into a separated struct so that it can be reused with properties across the project. Read more about Property Wrappers at Majid’s Blog post about Property Wrappers.
Here is an excellent use case of a custom Property Wrapper Daniel showed us.
@propertyWrapper
struct ToTwoPlaces {
private(set) var value: Double = 0
private let multiplier = 100.0
var wrappedValue: Double {
get {value}
set {
value = ((newValue * multiplier).rounded()) / multiplier)
}
}
init(wrappedValue initialValue: Double) {
self.wrappedValue = initialValue
}
}
As its name suggests, this property wrapper rounds a double value two places.
Let’s see some real-world application of @ToTwoPlace
propertyWrapper.
struct PriceTagText: View {
@ToTwoPlaces var price: Double
var body: some View {
Text(String(price))
.bold()
.padding(8)
.foregroundColor(.white)
.background(Color.green)
.cornerRadius(5)
}
}
First of all, I create PriceTagText
. It has its own style (which can be simplified by creating a custom ViewModifier). Notice the use of @ToTwoPlaces
. It’s clear from the first glance the number will be rounded to two places. The stored property, price
, will be used as a parameter for the memberwise initializer of this the PriceTagText struct.
struct ContentView: View {
@EnvironmentObject var exchangeRate: ExchangeRate
let priceInDollar: Double = 699
var body: some View {
let priceInPound = priceInDollar * exchangeRate.poundToDollar
return HStack {
Text("Dear Tim, $699 in pound is")
PriceTagText(price: priceInPound)
}
}
}
And the result is
Without the @ToTwoPlaces
property wrapper, the number would be 559.1373766138192.
Thanks for reading. If you have any thoughts or comments, please feel free write it down below. I’m really excited to see what you think about this. You can find source code of the examples in this blog post on this GitHub page. The next part of this iOSDevUK series will be about accessibility. Stay tuned!