Learning SwiftUI – Again

I wrote last week about the six-month app challenge I am working on; which is to release an iPad app in the next six months.

Over the past couple of years I have mostly been working with progressive web apps or in recent times a Maui app written in C#. I haven’t done much at all with SwiftUI for those couple of years, so this week I decided to take a refresher so that I could remember how SwiftUI apps work and are built. Native iOS dev is my favourite, but working on multi-platform codebases has been interesting too.

With Notic Meet being a SwiftUI-based app, I need to relearn this as I work on it, but I needed a quick refresher so that I could get started.

What I do remember being reasonably easy is the concept of how views work. I don’t mean to belittle a designer’s role when I say easy. I’m more meaning that the mechanics of using views is relatively simple. Making it look good is the real challenge.

A SwiftUI app begins in the “YourApp.swift” file which creates a scene with a WindowGroup and within that, the initial view is added. The default is called ContentView.

YourApp.swift could look like this:

var body: some Scene {
    WindowGroup {
        ContentView()
    }
}

ContentView is declared as a struct and conforms to the View protocol which requires a body that returns “some” view. When creating a new SwiftUI file you are given this:

import SwiftUI

struct Test: View {
    var body: some View {
        Text("Hello, World!")
    }
}

struct Test_Previews: PreviewProvider {
    static var previews: some View {
        Test()
    }
}

I called this view Test. It has a body that returns some View. Some is an opaque return type, meaning we must return a view. SwiftUI has many views built in, but as long as the view used conforms to the View protocol, then it can be returned. In this particular example, the view being returned is Text(“Hello, World!”) which puts that message in the middle of the screen.

One question you might have is about “returning” some View. You don’t see the word return in this code. That is because we don’t need it. Just having Text(“….”) is enough.

The Test_Previews struct is used to create a preview in Xcode to see what your app looks like as you build the view. This returns Test() which is the actual view. Although Test currently has no parameters, if it did we would need to pass in some fake data when we return Test in the preview. I’ll show how that works in a later post.

The neat thing about SwiftUI is being able to nest views in views. If we want to display more than just text, we can wrap them in a list, a vertical stack (VStack), a horizontal stack (HStack) and others. The example below shows how we can make a static table:

List {
    Text("Hello, World!")
    Text("Goodbye, World!")
}

We are still returning the single view, which in this case is a List, but within that list, we have two Text views.

We don’t need to use the SwiftUI-provided views. This particular view is called Test. We could pull Test into ContentView as follows:

struct ContentView: View {
    var body: some View {
        NavigationView {
            Test()
        }
    }
}

In the example above, the Test view is nested in a NavigationView. The NavigationView provides navigation for the project although it is lacking a title which can be added in just after Test as follows:

.navigationTitle("Test Nav")

To align text, change style such as colour, font etc… you can apply modifiers. If you add .padding() below one of the Text views you will see a default amount of padding being added around the text.

Text("Hello, World!")
    .padding()

I found this part of views very simple to follow. You return a View. It doesn’t matter what view you return as long as it conforms to View. This way you can build up the look of your app and add in modifiers to change the layout a little more.

The Plan

Notic Meet will be using SwiftUI. I am not experienced enough to know if it will work for all that is needed. A lot of UI will be pretty boilerplate. The app will have a simple look and layout. I don’t know SwiftUI well enough to know its weaknesses yet, although I will post my findings as I build the app.

The next step is to finish relearning SwiftUI because I will need things like core data, and CloudKit, as well as to understand the design patterns of SwiftUI. At the moment I am mostly familiar with just Swift and MVC as well as MVVM. I typically leaned more towards MVVM with my work in Swift in days gone past, but as of yet, I don’t remember too much about the structure of a SwiftUI app.

I am familiar with @StateObject, @Published, and @EnvironmentObject, but couldn’t explain that without having to study them quickly first. That will come though and I expect by the end of September there will be good progress to see something working for Notic Meet.

Leave a comment