
Static Types in SwiftUI - gok
https://www.objc.io/blog/2019/11/05/static-types-in-swiftui/
======
Razengan
Anyone who has managed to figure out anything substantial about SwiftUI has
done so purely through a labor of love.

It's a really amazing system, but the sparseness of proper official
documentation, Xcode bugs (like marking errors on a line far away from where
the problem actually is) and the seemingly secret Swift magic that's used to
implement some features, means everyone is stumbling blindly in a labyrinth,
relying on each other's shouts to navigate.

Resources like this post and [https://swiftui-lab.com](https://swiftui-
lab.com) and [https://mecid.github.io](https://mecid.github.io) are a godsend.

~~~
fpgaminer
Yeah, bit of a shame. I took some time to go through Apple's tutorial, just to
get a taste of SwiftUI, but I ran into Xcode crapping the bed every few
minutes; having to clean the build folder every time a new source file was
added; compiler bugs; and to top it all off there were a couple of places that
the tutorial was outdated already.

And of course you need to be on the bug riddled Catalina to get any real
SwiftUI development done (live previews).

UI development in the Apple ecosystem has always been a bit rough, but I've
never run into _this_ many problems in such a short amount of time, all while
following their official tutorial.

~~~
ta0xdeadbeef
I mean XCode has been a terrible experience for a lot of devs (C++ in
particular) for years. I completely avoid it, when you need it for a build
just invoke it from the command line. Some of the other stuff is tricky to set
up outside the UI so you need it, but other than that, XCode is not worth the
hassle imo.

Real shame too. I've talked about this with some of their tools team I went to
school with. I don't know what's in the water in Cupertino but I don't think
Apple devs are getting the same experience out of XCode as their actual users.

------
cerberusss
I'm having great fun building a SwiftUI app for a client. I haven't
encountered any showstoppers, but several times I've changed the design to
make it easier for myself.

To give you an example: pull-to-refresh isn't there yet. You have to build it
yourself. I looked for a searchbar and I built it myself as well.

However building the GUI itself is very fast, because it compiles and
immediately previews your code. The preview can be changed with the mouse,
which updates your code again. That aspect is very, very nice and made my
client smile when we were adjusting some padding, font sizes, image sizes etc.
on the fly.

~~~
bsaul
My personal showstopper was dealing with attributed strings. I couldn’t get an
equivalent of multiline uitextview of attributed string. It happened after
just 20 minutes building a real world app, which made me wonder if anyone has
ever built anything real at apple with this framework.

(Also, i couldn’t get a list of all the types of views and their documentation
anywhere in apple’s documentation).

~~~
Razengan
You can have attributed strings! After a fashion:

    
    
        Text("Hello,").italic() + Text("World!").fontWeight(.bold)
    

Works with multiple lines, multiple font sizes etc.

Another undocumented gem that I discovered via the SwiftUI community. You
should be able to build a constructor that reads a string with formatting
codes like Markdown and spits multiple Text views.

------
yawaramin
How does the conditional type inference work? E.g. from the article:

    
    
        let stack = VStack {
            if myState {
                Text("Hello")
            } else {
                Rectangle()
                    .fill(myState ? Color.red : Color.green)
                    .frame(width: 100, height: 100)
            }
        }
    

Type:

    
    
        VStack<
          _ConditionalContent<
            Text,
            ModifiedContent<_ShapeView<Rectangle, Color>, _FrameLayout>>>
    

How does an `if` expression get inferred as a type `_ConditionalContent<...>`?
Is there some magic support for SwiftUI in Swift? Does it desugar into
something like:

    
    
        let stack = VStack {
            ConditionalContent(myState,
                Text("Hello"),
                Rectangle()
                    .fill(myState ? Color.red : Color.green)
                    .frame(width: 100, height: 100))
        }
    
    ?

~~~
favorited
It's using a not-yet-offical feature of Swift called "function builders." It's
basically a way to walk through each Swift statement inside a function and
build an aggregated value, including maintaining all of the type info.

So the language feature isn't tied specifically to SwiftUI (though SwiftUI is
the only supported client at this point), but it supports that general kind of
transformation.

[https://github.com/apple/swift-
evolution/blob/9992cf3c11c2d5...](https://github.com/apple/swift-
evolution/blob/9992cf3c11c2d5e0ea20bee98657d93902d5b174/proposals/XXXX-
function-builders.md)

~~~
yawaramin
Oh that's interesting, thanks! It seems almost perfectly designed to fit
SwiftUI's use case. I wonder what other use cases it enables.

~~~
favorited
People have done some cool stuff with it! My favorite is this one, which
builds an NSAttributedString:

[https://github.com/ethanhuang13/NSAttributedStringBuilder](https://github.com/ethanhuang13/NSAttributedStringBuilder)

~~~
yawaramin
Oh, very cool. And now that I think about it, this can be used to make all
sorts of builders. E.g. SQL comes to mind. Something like:

    
    
        let query = Sql {
            Select(["baz.foo", "quux.bar"])
            From("baz")
            InnerJoin("quux")
            On(Eq("baz.id", "quux.id"))
        }

------
markbaikal
The trick of using more compile-time knowledge to avoid diffing the tree of
elements seems similar to svelte ([https://svelte.dev](https://svelte.dev)) in
the Javascript world.

------
arianvanp
How does this type inference stuff work? Is the if expression overloaded in
this case? Or does if always return the disjunction of two types in swift?

In other languages like rust and Haskell, the branches of if need to agree on
their type so I found this a bit confusing.

Is there some kind of embedded DSL stuff going on here?

~~~
favorited
> Is there some kind of embedded DSL stuff going on here?

Exactly. It's a (at this point, unofficial) Swift feature called "function
builders." The types end up being the same, because the conditionals are
represented as wrapper types.

So

    
    
        if count == 0 {
          EmptyView()
        } else {
          Text("\(count)")
        }
    

would result in a type something like `Conditional<EmptyView, Text>`.

[https://github.com/apple/swift-
evolution/blob/9992cf3c11c2d5...](https://github.com/apple/swift-
evolution/blob/9992cf3c11c2d5e0ea20bee98657d93902d5b174/proposals/XXXX-
function-builders.md)

