Looking in to SwiftUI
Tags: swiftui, programming, devdiary
Published: 2020-07-01 16:23:31

One of the most exciting things to come out of the last couple WWDC's is Swift UI. If you're unfamiliar, it's a UI framework that makes writing UI code much lighter and easier by using a lot of concepts that have been popularized by things such as React.

Swift UI is clearly the future of Apple's platforms, and since I'm learning this stuff from scratch anyway, I may as well embrace the future. So my new app will be written in as close to 100% Swift UI as I can manage, and require iOS 14.

But, now I've just added something else I have to learn. Luckily, it seems like a lot of Swift UI's syntax is built upon the basics of Swift, so learning both together shouldn't be too bad.

The first thing I did was to try and figure out what all Swift UI is capable of. Luckily Apple has some great tutorials over on [their developer site](https://developer.apple.com/tutorials/swiftui) to help get started. These have been an invaluable resource and I'll be sure to reference them as I get going.

The other place I've been spending my time to try to get my head around what SwiftUI can do is on [Paul Hudson's YouTube channel](https://www.youtube.com/channel/UCmJi5RdDLgzvkl3Ly0DRMlQ). These have been *especially* great. I'm not sure what it is about his explanation style, but his videos have led to more "aha!" moments when it comes to understanding the major concepts than most.

I started out with this [video on `NavigationView`](https://youtu.be/nA6Jo6YnL9g), which is one of the simplest and most basic concepts in a UI stack. A few of the major things I learned here:

- A `navigationBarTitle()` is called on a view *inside* the `NavigationView`, not on the view itself. Why? Because a `NavigationView` can contain many sub-views, and each sub-view could/should/will have it's own title. This means that the following simple `NavigationView` stack looks a bit weird:

```swift
struct ContentView: View {
  var body: some View {
    NavigationView {
      Text('Hello world')
        .navigationBarTitle('Navigation')
    }
  }
}
```

Looking at this code you would think you'd apply `.navigationBarTitle` on the `NavigationView` itself. But this is simply because SwiftUI is handling something really clever: everything is a View. Views are the most basic foundation of SwiftUI, and so when you create a `Text()` it's actually not just creating the text itself, but also the entire wrapping view the text lives in. So as your `NavigationView` hierarchy gets more complex, this makes more sense:

```swift
struct ContentView: View {
  var body: some View {
    NavigationView {
      VStack {
        Text('Hello world')
      }.navigationBarTitle('First View')

      VStack {
        Text('Hello world, again')
      }.navigationBarTitle('Second View')
    }
  }
}
```

Now it's easier to see what's going on, and why we'd want to apply the title to a sub-view and not the `NavigationView` itself.

- `NavigationLink` seems to be the way SwiftUI wants you to dig into and out of `NavigationView` stacks. But, you can get around this and use custom `Buttons`'s if you bind them to certain variables

I left the video with a bunch of questions, though. 

- Why does the wrapping view struct implement the `View` protocol as `struct ContentView: View`, while the `body` property does `body: some View`? What does `some View` mean?
- In the video he applied some decorators to his variables like `@State` and `@ObservableObject` which I have no idea what they do. He also sometimes passed a variable as it was named, and sometimes with a `$` in front of it.

That's fine, I've only just started looking at SwiftUI code, let alone understanding it.

And it just so happens that there's a video on the same channel that explains this: [What's the difference between @State, @ObjectBinding, and @EnvironmentObject?](https://youtu.be/stSB04C4iS4)

This video was *awesome*, and it explained so many wonderful things to me

- SwiftUI's views are all structs, not classes.

    Why is that important? Because a `struct` is *passed by value* whereas a `class` is *passed by reference*. Additionally, once you've created a struct, it's immutable and can't change. This makes sense if you think about it in terms of another type of struct, a `number`. Once you create the number `5`, you can't change what the number `5` means. This is different to a `class` which is instantiated and its location in memory is referenced. Once you initialize a `class`, not only can you update its properties, but all other references to that same `class` *instance* will also instantly get those changes.

    How does this relate to structs? Well, if our view structs were permanently immutable, then we'd never be able to update them with new data. To solve this issue, SwiftUI provides the `@State` and `@ObjectBinding` decorators. What these do is they tell SwiftUI that *these specific variables* might change, and if they do, then the View should re-render.

    What's the difference between `@State` and `@ObjectBinding`? Simple: a `@State` has one-way binding, meaning data only flows one direction, while `@ObjectBinding` has two-way binding, meaning it can change in both directions.

- This also answers the question I had earlier about why some variables had a `$` in front of them. When they do, it means that they're bound, and therefore should be monitored for changes. Without it, the compiler will just fix them to their value during compile time.

---

These videos have been hugely helpful so far, and Paul is a joy to watch. I'll be checking out more of [his SwiftUI videos](https://www.youtube.com/playlist?list=PLuoeXyslFTuaZtX7xSYbWz3TR0Vpz39gK) as I learn. But I think at this point I understand enough of the code being written in these videos that I can start prototyping some parts of my app. The best way to learn is by doing.