SwiftUI first impressions / pain analysis
Tags: swift, swiftui, macos, xcode
Published: 2020-03-18 22:38:49

---
title: SwiftUI first impressions / pain analysis
published: true
description: I'd heard about this new-fangled "SwiftUI". It was only this week that my urge to self-flaggellate was strong enough to try it.
tags: #swift #swiftui #macos #xcode
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/x93p3k8byu7keytrthw9.jpeg
---

For years I've been occasionally dabbling in macOS native application development, and for years I've been resisting the urge to throw my MacBook out the window. Any delusions I've occasionally had about releasing native macOS apps have been flattened by the AppKit pain train.

Where's my Delegate? Or was it the Controller, Model, or View that I needed? Was it in my Storyboard? Xib? Nib? Jib? Why is Xcode crashing? What is this non-deterministic compiler error? 

I can see how a dedicated developer could become a weapon with AppKit, but if you're multi-disciplinary the time input/reward ratio is just way off.

Apple has presumably realised this, hence the new kid on the block: SwiftUI. I'd heard about this new-fangled "SwiftUI". It was only this week that my urge to self-flaggellate was strong enough to try it. So I fired up Xcode, and...

Well. What a pleasant surprise. Everything, and I mean the whole damn production, is boiled down into one glorious concept: The `View`.

This rustles my jimmies in all the right directions. The only way I ever made any progress with AppKit was to ignore its psychotic smorgasbord of concepts and build self-contained `NSView` subclasses. Then, those subclasses could be composed into a UI.

That's effectively SwiftUI in a nutshell. You create `View` implementations, and then you add them to each other. That's it.

`View` is a protocol, not a class. No inheritance. You have full flexibility to initialise this bad boy however the hell you want. They're just fresh-off-the-stack structs with a `.body` property requirement.

Could it get better? Yes it could get better. Some people are imperative people. The want to tell you _how_ to do something, rather than _what_ they want done. These people have titles like "[insert JavaScript framework] Evangelist" and you should socially distance yourself from these people.

Better people are declarative people. They tell you what the objective is, and then leave you alone to achieve it. SwiftUI is a declarative person. The difference in code:

```python
# Imperative Python
relevant_heights: List[int] = list()
for tree in forest:
    if tree.age == 4:
        relevant_heights.append(tree.height)
return sum(relevant_heights)

# Declarative Python
return sum([t.height for t in forest if t.age == 4])
```

In the first example, we told Python how to find the right tree heights. In the second example, we told Python what we wanted and let it work out the implementation details itself.

If you've ever worked in SQL, you will be familiar with the declarative style, because SQL is entirely declarative:

```sql
/* Declarative SQL */
select sum(height)
from   trees
where  age == 4
```

The declarative attitude is the one required to grok the following:

```swift
struct Header: View {

    var body: some View {
        VStack {
            Text("Top row text")
            Text("Bottom row text")
        }    
    }
}
```

We declare that we would like a vertical stack of views (`VStack`), inside of which we would like two pieces of text (`Text`).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/dmmrbb90gcaifbp2cxlr.png)

When I first saw this, I was frustrated. Where exactly do we return from inside the `VStack`? And what is returned? How can two `Text` declarations magically turn into two lines of text?

Being an absolute SQL fanatic, I found peace by accepting that we are declaring _what_ we want rather than _how_ we want it done. Writing Swift code against the SwiftUI API is more like writing SQL than say, imperative AppKit code.

We can mix and match views willy-nilly. Say we declare an `H1` view, which in our application will be roughly analogous to `<h1>` in HTML:

```swift
struct H1: View {
    
    let headingText: String
    
    var body: some View {
        Text(headingText).font(
            .system(
                size: 32,
                weight: .bold,
                design: .default
            )
        )
    }
}
```

We can now use `H1` inside our earlier `Header` example:

```swift
struct Header: View {

    var body: some View {
        VStack {
            H1(headingText: "Top row text")
            Text("Bottom row text")
        }    
    }
}
```

Producing:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/jzqj39q5v0hab3mbo8s8.png)
 
That really is it, kids. Everything else is a variation on the them of defining `View` implementations and composing them together. Nested hierarchies of `View` become your application user interface.

What a pleasant surprise. SwiftUI might be a keeper. Some quick summary thoughts:

## Good

- Everything above
- Xcode doesn't crash constantly anymore
- Swift package manager is great now

## The Bad

- Not many built in controls, re-using AppKit classes (e.g. NSTableView) quickly becomes necessary
- AppKit / SwiftUI interaction is poorly documented
- All the Apple docs are (surprise) focused on UIKit people, & iPhone GUI paradigms

Want to dive a little deeper? In a follow up, I discuss [how to integrate an AppKit NSTableView into a SwiftUI View hierarchy](https://dev.to/hugh_jeremy/adding-an-nstableview-to-a-swiftui-view-212p).

- [Hugh](https://twitter.com/hugh_jeremy)