I’m not certain how to phrase this. It’s either that I wish I was better at predicting what a SwiftUI view would look like, or that I wish SwiftUI was more predictable at how views render in different contexts. I recently built a multi-platform SwiftUI utility app, and was struck by how often I ran into unexpected results.
Contextual rendering of a view is a feature, perhaps a key feature, of the SwiftUI framework. The most obvious example is how views render differently by platform. A default button renders differently on macOS as compared to iOS. But this “different contextual representation” goes much deeper. Some views render differently based on if they are enclosed by another view, such as Form or NavigationView.
If you take the example in Apple’s reference documentation for Form, and replace the Form with a VStack, the result is notably different. For the following two screenshots illustrating the differences, I stripped out the enclosing Section views. The view on the left shows the view enclosed within
Form, the view on the right shows the content enclosed within a
Example code at https://gist.github.com/heckj/72f713faf28014e560449f82b7ab357d
I feel obliged to point out that these effects, at least in the case of Form, are documented within the reference documentation for Form. That said, I’m fairly certain that not all view variations are explicitly documented.
In general, the combined effects of views get complicated — and hard to predict — as you compose them, primarily within container views. I do wonder if the struggle to predict how a view will render (and that they render contextually) is responsible for some of the feelings I’ve heard expressed by developers as “SwiftUI isn’t ready for production” or “It still feels beta to me”.
The productivity enhancement of being able to preview a view “live within Xcode” has gone a long way to mitigating this complexity for me, especially when constructing views that I want to operate across multiple platforms (macOS, iOS, iPadOS). Using Xcode 14 beta, the automatic live rendering is notably reducing the time for each iteration loop (barring a few odd bugs here and there – live rendering for macOS seems to come with notably more crashes while attempting to generate a the preview).
The best advice I have to counter this difficulty in prediction is to lean into the previewing – be it for macOS, iOS, tvOS, or watchOS. Use Xcode’s previewing capability, and get to your combined views as quickly as possible. While it can be surprising that an enclosing view can have such an impact on how something renders, seeing the combination so easily while developing at least lets you verify and react when things don’t go as you expect.