Monday, June 3, 2019

SwiftUI and Combine

SwiftUI:

SwiftUI is an innovative, exceptionally simple way to build user interfaces across all Apple platforms with the power of Swift. Build user interfaces for any Apple device using just one set of tools and APIs. With a declarative Swift syntax that’s easy to read and natural to write, SwiftUI works seamlessly with new Xcode design tools to keep your code and design perfectly in sync. Automatic support for Dynamic Type, Dark Mode, localization, and accessibility means your first line of SwiftUI code is already the most powerful UI code you’ve ever written.

I guess this is project Amber. I don’t know the details well enough to say much yet. But I think building UIs in code with a functional/declarative style is fundamentally the right approach. The code snippets look similar to (but better than) the newer UI code I’ve been writing using my own layer on top of AppKit.

As you work in the design canvas, everything you edit is completely in sync with the code in the adjoining editor. Code is instantly visible as a preview as you type, and any change you make to that preview immediately appears in your code. Xcode recompiles your changes instantly and inserts them into a running version of your app, visible and editable at all times.

The Swift compiler and runtime are fully embedded throughout Xcode, so your app is constantly being built and run. The design canvas you see isn’t just an approximation of your user interface — it’s your live app. And Xcode can swap edited code directly in your live app with “dynamic replacement”, a new feature in Swift.

At first I thought SwiftUI was a wrapper layer on top of AppKit and UIKit.

Robert Clegg:

It really isn’t. It’s built from the ground up and is all Swift code.

If so, this is really interesting as it introduces a separate UI stack and really makes Objective-C a second-class citizen. But it is also a chance to have a unified framework that can apparently coexist with legacy views in the same window.

Nate Cook:

SwiftUI works great with UIKit, AppKit, and more! This tutorial shows how you can host SwiftUI views inside view controllers, and then embed those view controllers in SwiftUI

Jack Lawrence:

Remember all those awesome UX #WWDC talks about interruptible animations, and how they make your app feel far more responsive? Getting it right used to be incredibly hard. #SwiftUI does it all for you with One. Line. Of. Code.

Combine:

The Combine framework provides a declarative Swift API for processing values over time. These values can represent user interface events, network responses, scheduled events, and many other kinds of asynchronous data. Combine declares publishers to expose values that can change over time, and subscribers to receive those values from the publishers.

This is Apple’s reactive framework (finally) and the successor to Cocoa Bindings and KVO.

Previously:

Update (2019-06-04): Joe Groff:

Some things wrap UI/NS views, but whether they do, and what view type they wrap, is subject to change. Best to think about it as a distinct thing

Joe Groff:

SwiftUI controls have layers that are managed directly by the framework; there are APIs for embedding an NS/UIView in SwiftUI and vice versa. Performance was a top priority, it’s good

Joe Groff:

Any transform that can change visibility or structure gets represented by a generic wrapper in Swift, so it’s known that opacity/scale/rotation/etc. can change, when content can have variable numbers of nodes, etc. Only the variable cases need “ids” for diffing

Kyle Howells:

You don’t build an entirely brand new UI framework from scratch if you intend the other to be around long term.

Best case you reimplement everything twice in both frameworks forever, or they diverge and you get diff behaviours in each over time (like adding swipe to delete).

Olivier Halligon:

Sooo... This is what’s likely behind that strange SwiftUI! 🕵️‍♂️ (you know, with no commas and still an if statement inside that StackV)

There’s now a forum thread.

David Smith:

Let’s see, names this project has had…

Pipelines
Dataflows
KVO2
PubSub
Combine

am I forgetting any? 😂

JP Simard:

I’m assuming the SwiftUI @State keywords are @dgregor79’s Property Wrappers currently being pitched in the Swift Forums.

Daniel Jalkut:

If you were lost when Apple used $ in $variableNames during coding demos, it comes from this addition to Swift.

Jordan Rose:

Yeah, it has too many system components to backwards-deploy, sorry. But it supports all the usual weak-linking / availability stuff, so if you want to mix-and-match for new views in existing apps you do have that option.

Jeff Nadeau:

Localized by default. In fact, if you want to display un-localized text from model data or internet sources, you use the Text(verbatim:) initializer instead.

Kyle Howells:

I’m actually incredibly disappointed that SwiftUI seems to be a new UI framework, not written on top of UIKit.

Declarative UI frameworks are great for simple straight forward UIs that fully their preconceptions. But if you want to violate those they are a massive pain!

If it was built on top of a normal imperative UI framework you could drop down to the real power of a normal framework instead of dancing through hundreds of hoops to make it work.

I’m fearful this will regress iOS UI into more bland plain simple UIs even further than iOS7.

Corbin Dunn:

I also worry about customizability.

Jeff Nadeau:

Most things are customizable (or will be when API lands). The controls do some indirection through a Style type that lets you implement whatever appearance and behaviors you want.

It’s just a matter of getting to everything since there are so many widgets on the Mac

Patrick Balestra:

Creating a brand new project in Xcode 11 doesn’t create a Main.storyboard anymore, everything is defined in code.

Joe Groff:

One place Swift really helps with performance compared to other Reactish frameworks is the type system. The static subset of the view graph is encoded in the type system, so the runtime knows it can’t change and only has to diff the dynamic parts. 120hz update was a P0 goal

Daniel Jalkut:

It’s still sinking in for me that Apple effectively deprecated ALL of their UI frameworks yesterday. Mac, iOS, tvOS, and watchOS developers are equally displaced.

See also: Hacker News.

Kyle Howells:

Two things Swift (and looks like SwiftUI now too) fall down on is lack of understandability/predictability and reasoning about perfo; and being seemingly simple but having a very steep difficulty curve when you get into the details.

Zhuowei Zhang:

Apple: Swift is a system programming language that can replace C++
Also Apple: writes new #SwiftUI library in C++

In fairness, most of SwiftUI is written in Swift! It’s just the scenegraph that is in C++. I wonder why they did that. Is there an older library that they reused?

Jeff Nadeau:

SwiftUI does not require Catalyst (it interfaces with AppKit directly on macOS), but it does work in Catalyst apps if that’s what you’re building.

Russell Ivanovic:

iOS Devs: “ha ha only 10% of Android devices are on the latest OS”

Also iOS Devs: “I can’t touch SwiftUI for another 2 years because I have to support older iOS versions”

Android Devs: “Oh Google shipped a new framework? I’ll update my AndroidX package and start using it today”

Update (2019-06-20): Jeff Nadeau:

A feature of this screen I took from today’s Introducing SwiftUI talk, and something I think will be very typical.

Look at the shape of the code: state, var body, and functions. The body is all nouns, and then all of the verbs follow in separate functions.

Personally I think this separation is wonderful. It keeps the event-reactive code out of the DSL and very cleanly demarcates “deciding what to show” vs “deciding what to do”.

Rob Mayoff:

Order of modifiers in SwiftUI view impacts view appearance

[…]

It is better not to think of the modifiers as modifying the MapView. Instead, think of MapView().edgesIgnoringSafeArea(.top) as returning a SafeAreaIgnoringView whose body is the MapView, and which lays out its body differently depending on whether its own top edge is at the top edge of the safe area. You should think of it that way because that is what it actually does.

Jonathan Wight:

Quick example.

This is NSOutlineView uses a SwiftUI HStack (or rather many…) for each row.

The (unoptimised, in need of a refactor) method for outlineView(viewFor:item:) is shown.

I think this code plays to both Cocoa’s and SwiftUI’s strengths

Majid:

I will try to show you real-world app example written entirely in SwiftUI. Let’s build an app searching for Github repos. We need a screen with a text field for typing a query and a list of repos which comes from the search query.

John Sundell:

Declarative UI programming patterns have become incredibly popular over the last few years. On the web with frameworks like React and Vue.js, in cross-platform development environments like React Native and Flutter, and through native tools like RxSwift and RxCocoa — declarative UIs and the reactive principles behind them have truly taken many development communities by storm.

It’s therefore especially exciting to see Apple step into this scene, with their own, completely native declarative UI framework — called SwiftUI. While there’s a ton of functionality to be discovered and experimented with in this new UI framework for all of Apple’s platforms — let’s start by taking a first look at some of the fundamentals of SwiftUI, and how it lets us drastically reduce the amount of code needed to produce common forms of UIs and interactions.

Rui Peres:

First, how I feel as a developer and as a person that has dedicated a tremendous amount of time to FRP* (both as a dev, contributor and evangelist). The release of Combine is the realization that the investment I have been making all these years made sense and it's also the confirmation that the industry is moving on this particular direction.

Adam Sharp:

Combine has very different thread safety guarantees than I’m used to coming from ReactiveSwift, which goes to heroic effort to ensure that events are always delivered serially, and never recursively.

John Sundell:

While it’s quite easy to initially look at SwiftUI as just a declarative API written right on top of UIKit (and in some ways it is), it’s so much bigger than that. While it’s true that, at the end of the day, any SwiftUI view hierarchy will get resolved into some form of UIKit/AppKit/CoreAnimation representation — there’s not a simple 1-to-1 mapping going on here.

Dave Abrahams:

SwiftUI layout isn’t a constraint system—or you could say we just have one-way constraints between parents and children. Most of the time, that’s enough, but if you need generalized constraints you can bridge views to UIKit and use autolayout.

Joe Groff:

The eventual goal is to allow all your UI code to be done in SwiftUI. Whether and how things map to UIViews is subject to change

Daniel Jalkut:

I’m going to throw some more worms into this compost bin. Another huge “mind blown” realization I had (with help) today: SwiftUI means “views” are essentially free. Zero overhead. Declarative UI is as cheap as any other struct. Huge shift from UIView, even more from NSView.

Shai Mishali:

Myself, and Gett, are heavy users of RxSwift — so as part of my learning process, I’m trying to make a map of things that correlate directly between RxSwift and Combine.

Casey Liss:

In order to discuss a Combine, one has to discuss the main differences between it and RxSwift. To my eyes: there are three.

Matt Gallagher:

Apple’s Combine talk at WWDC didn’t mention “reactive programming” or any background to the field. When presenting functions with the same interface as standard reactive transforms they said “we’ve designed”. It was the most blinkered, isolationist talk I’ve seen.

Bruno Rocha:

The new Swift features that are spawning out it are also game changing, and I for one am ready for the addition of new compiler black magics into Swift.

Chris Eidhof:

SwiftUI still seems to be full of bugs, making it hard to learn. You don’t know if it’s you making a mistake, or the implementation. Here’s another one[…]

Eric Lewis:

There is so many gotchas in SwiftUI. Especially around lists.

Wil Shipley:

The other (real) complaint is there’s no good reason this was secret. It’s not like Apple just invented reactive programming. This could have been done with community input.

Apple’s making this common mistake where they’re like, “Oh boy, we created something amazing with help from a huge community working together — now we should add our own private surprise stuff because surely we know better than everyone else in the whole world combined.”

Brent Simmons:

The future of app-making looks more and more like web development. Declarative. Semantic. Dynamic — adapting to context (interaction styles, accessibility settings, screen size, etc.). Runtime-editable.

Andrew Pontious:

I’ve never seen an abstraction layer high enough up to make cross-platform apps work well enough to be something I’d like to use for native apps.

Everyone keeps trying to reinvent the web, but for native, this time.

But the web exists for a reason. It was supposed to give us cross platform functionality without being native. And it works!

[…]

Apple fought cross-platform layers for so many years! And we cheered along with them!

And now, suddenly, due to their own strategic moves, they have too many platforms to develop for individually.

Same problem they brushed aside when it was only our problem!

Paulo Andrade:

While I’m very excited about SwiftUI, this type of stuff is what scares me most about letting the framework “do the right thing”. Sometimes you might want a slightly different behavior than what the framework does and you’re down the rabbit hole trying to make that happen.

Craig Hockenberry:

This is exactly why I think Apple has a HUGE advantage over other systems. Their solution must adapt for interaction sizes as small as a watch face and as large as a TV screen. That requirement means it must be control independent, thereby allowing a native platform feel.

Brent Simmons:

I have not watched WWDC videos so avidly, and with so much glee, in a decade.

Brent Simmons:

I’m surely not the only person to think, all week long, that this WWDC marks the end of Apple’s NeXT era and the beginning of the Swift era.

Matt Gallagher (tweet):

This article will look at how SwiftUI’s approach to declarative views compares to CwlViews, why the two approaches differ and what Apple changed to make this possible.

[…]

Long term, SwiftUI will be good but it’s going to be years of transition before most projects have a minimum deployment target of iOS 13 or macOS 10.15. As with the first year or two of Swift development, I expect a lot of hastily started, poorly implemented and quickly forgotten projects. The SwiftUI implementation, its API and associated tooling are likely to change rapidly as serious bugs and gaping holes are patched.

Colin Cornaby:

SwiftUI is amazing because it doesn’t feel like there are any losers. It makes the Mac better. It makes the iPad better. It makes the iPhone better. Heck, it even makes the Apple Watch and Apple TV better. I’m thinking about ways to ship apps for the TV and Watch, and I never would have considered that before. I even have Mac apps I might bring to iPad. I didn’t want to give up the power of AppKit on the Mac, and I didn’t want to maintain two separate code bases. Now I don’t have to choose.

Craig Hockenberry:

Something I haven’t seen discussed: how size classes will be handled in SwiftUI.

I realize it’s still early days, but this is a pretty important aspect of devices like the iPad, where screen real estate varies widely.

“Just add some conditional logic” hurts the abstraction.

Steve Troughton-Smith:

SwiftUI is really great for AppKit developers because it does give them a path forward that is cross-platform and isn’t ‘port to UIKit’. But I don’t see SwiftUI currently capable of replacing complex AppKit-specific Mac UI any more than UIKit; that could be some years out

Erica Sadun:

In fact, as a developer, I’m not happy about not having direct control over the tightness of either layout or an obvious way to relate ZStack siblings. If there’s a way to describe how much content hugging I want in a ZStack layout and how to prioritize which item in that layout should guide the others, I haven’t discovered it. If you have, please let me know!

Craig Hockenberry:

But I think there’s something important to add to his note: the SwiftUI DSL describes the most capable environment. It’s the maximum interaction surface: platforms will render and react to a subset of what’s declared.

Colin Cornaby:

Are master/detail editable views a problem in SwiftUI right now? If you have an array of structs, and a detail view that edits one of the structs, there’s no way to commit the edit to the master array it seems like.

Joe Heck:

Color, Layout, and graphics design are all clearly customizable with SwiftUI. I also expect that some of the crazier innovations (such as the now common “pull to refresh” gesture) will become significantly harder to enable from declarative structures. By its very nature, the declarative structure will make the common, well established UI elements easy and accessible, so much so that I wouldn’t be surprised to see a lot of early SwiftUI apps to “all look alike”. I expect the impact of “all looking alike” to drive a number of IOS dev teams a bit nuts.

The “escape hatches” to do crazy things clearly do exist – and while I haven’t reached that level of learning with SwiftUI, it does seem to follow the “make easy things simple, and hard things possible” concept of progressive disclosure.

It will be interesting to see what happens this fall when the first SwiftUI apps become available as experiments and where that takes consistency and usability on the Apple platforms.

Tanner Bennett:

It seems every single WWDC session on SwiftUI and Combine I’ve watched have managed to avoid talk of graceful error handling.

If someone could please point me to some resources on this, I would be very greatful. For example, displaying an alert when refreshing a feed failed.

Drew McCormack:

One thing I won’t miss is autolayout. Feels like the layout system in SwiftUI is an admission that autolayout was a dead end. It can live out its days with Garbage Collection and Java Cocoa. (Or perhaps it will remain, but only as an implementation detail.)

Kuba Suder:

Prepare to feel like you’ve just started learning Mac/iOS programming… This is a completely new thing which works in a completely new way, and it’s hard to switch your brain to a new mode. You will be thinking “How the hell do I do X” every step of the way.

[…]

Long term, I imagine the way it’s going to work is that SwiftUI (and possibly some related new frameworks) will gradually take over more and more parts of the underlying platform UI frameworks, to the point where they eventually just disappear. We’ll be writing a single codebase with SwiftUI and it will render differently on each platform, with some customizations required for each platform, but it’s possible that we’ll need less and less of those going forward, as the framework will get smarter.

Jaanus Kase:

In the old UIKit/AppKit world, view controllers were a central building block, and did a lot of manual shuffling between view and model. In the SwiftUI world, the view binds directly to the model, the glue is gone, and I have yet to figure out if there is any “logic” left which previously lived in ViewControllers and would still need to exist, or can I just forget about the whole ViewController concept.

Guilherme Rambo:

So apparently the way Apple found to hide SwiftUI (Amber) from the eyes of curious engineers was to implement it in a framework called “TimerSupport” lol

Drew McCormack:

Rather than hacking a DSL into the Swift language for SwiftUI, I think I would have preferred they add a data format based on Swift syntax. Like JSON is to JS.

Joe Groff:

We’d considered this. The problem with that for UI, and historically with nibs, is that if you outgrow what the data language can do, then you’re stuck rewriting a programmatic UI. By using code, the DSL, mix regular and DSL code, and also DSL and Kit components

About-SwiftUI:

The goal of this repository is to gather all this information having an unique place where looking for info about SwiftUI.

Update (2019-06-24): Mike:

Hmmm, looks like CareKit uses Combine and CoreData as a local database… And this project is open-source so you can get a glimpse how to use Combine in the wild!

Jeff Nadeau:

The SwiftUI Environment is extensible, if you want to propagate your own custom values hierarchically. Once you define a property on EnvironmentValues, you can push new values using the .environment modifier and a KeyPath to your property.

Update (2019-10-13): David Smith:

Well, the final version [of Combine] that actually shipped isn’t my work, but the original concept is simple enough: make KVO composable, then strip it down to just the most core concept (data streaming) by replacing all the options and parameters with composition.

My first prototype was an alternative to NSFileHandle of all things, but some friends on another team were like “you know if you replace all those NSData*s with ids it looks a surprising amount like something we were prototyping, let’s join forces”.

17 Comments RSS · Twitter

What I find a little bit disconcerting about SwiftUI at first glance is that it mixes so many different things into the same thing. You iterate over your data, pick which UI elements to show, bind data to them, define which elements are shown as starred, make functional decisions about how things behave, make layout decisions, set things like text and background colors, all in the same section of code. I'm not sure if the intention is that people will actually use it like that, or if that's just example code to introduce these concepts, but if it's the former, then this feels like it's going to be a messy refactoring minefield five years down the line.

@Lukas Good point. Hopefully that’s just for demo purposes, to show everything at once compactly. The AppKit sample code was not well factored, either.

I've seen differing opinions about whether SwiftUI actually contains a new UI framework (reimplementing tons of UIKit/AppKit), or is a framework on top of either of those that generates corresponding objects from UIKit/AppKit at runtime. Does anyone know definitively?

The reactive programming wave is beginning to ebb in web programming so how long until it does so in the rest of the programming community?

I've worked on largish projects using reactive techniques and frankly, now I've some experience with it, I wouldn't choose to repeat the experiment. I appreciate it's very popular with folks but it mostly seems to be used as cover for minimising up-front thinking and poor object-oriented design.

As long as I'm not compelled to SwiftUI I won't complain.

Looks like a more polished version of Google's Flutter, with better tooling (GUI builder for Flutter are... subpar, to the point it's better to write reactive code on VSCode...) and a nicer language (not that Dart is bad, tho')

[…] SwiftUI and Combine […]

I'm sticking with Objective-C and AppKit ha!

What bothers me is the mixed messages.

APPLE: Wow, we've really fixed UIKit this year! For example, @IBSegueAction totally solves the problem you've been complaining about since the birth of storyboards, where everything funnels through `prepareForSegue` in a horrible messy ugly bottleneck and you can't call an initializer on the destination view controller. ME: Sounds great! This is the way it should have been all along! APPLE: And by the way there are no more segues and no more view controllers. Switch to SwiftUI instead. ME: Huh?

The last time I saw messages this mixed coming from Apple during a WWDC was 1996 (Copland, OpenDoc, and Java). It was obvious to everyone that Apple was lost or lying (or both). And they would have gone down the tubes in Steve Jobs hadn't ridden in on a white horse and saved the company. Just saying.

Jeff barbose

Just how much has Swift as a language exploded in terms of vocabulary in order to make SwiftUI happen? It’s a bit disingenuous to say it’s all possible “through the power of Swift” when it needed to much more in order to power it.

Is Swift still easy to learn? does it provide a continuous curve to mastering it? I’m not so sure.

Leave a Comment