Swift UI makes simple UIs easier, moderately complex UIs harder, and very complex UIs impossible. The moment your UI is more complex than a stack of stacks, the elegance and comprehensibility falls apart compared to autolayout. It starts to feel like CSS all over again, using trial and error to try out combinations of elements and properties with unclear interactions.
The pattern it enforces is theoretically great, but you will get much more mileage out of learning to write in a "reactive" style manually (When state changes, update view to match. It doesn't need to literally be a function of state to make it a function of state. E.g. don't leave ifs without elses.)
A perfect combination would be a SwiftUI-style UI editor (sans bugs) to define UI, constraints included, but traditional layout management at runtime. Well, that or a ground-up redesign of SwiftUI's API.
I’m a lot happier with UIKit/AppKit plus SwiftUI than with just SwiftUI alone.
I wrote a couple of small sized apps trying to use only SwiftUI “the right way” to learn the framework and as you say whenever I wanted to do something specific with a lot of control I’d hit a wall with SwiftUI and have to go crazy with wild work arounds and trial-error throw spaghetti at the wall or
just give up.
Now I’m writing another app and making heavy use of NSViewRepresentable use AppKit from SwiftUI, and NSHostingView to embed SwiftUI in AppKit views. I’m using mostly SeiftUI at the “leafs” of the view hierarchy, and AppKit towards the root; all my windows use a NSWindow subclass and/or a view controller.
I find creative visual styling of views like drawing paths/shapes, drop shadows, quick stacks/rows, grid panels, etc all much easier and faster with SwiftUI and SwiftUI #Preview.
> Swift UI makes simple UIs easier, moderately complex UIs harder, and very complex UIs impossible. The moment your UI is more complex than a stack of stacks, the elegance and comprehensibly falls apart compared to autolayout. It starts to feel like CSS all over again, using trial and error to try out combinations of elements and properties with unclear interactions.
Sadly, this has been my experience. I built a moderately complex app, only to bump into more and more problems, and I find myself fighting the framework, building hacks, and implementing workarounds. When you venture into more advanced UIs, the leaky abstraction comes back to haunt you.
I haven't used Swift UI, but I have used Elm, React (a bit), and Flutter (a fair amount). My understanding is that it's a similar model.
In those frameworks (particularly Flutter, which generally has less ceremony), I have found simple UIs easy, and complex UIs slightly harder to build, but then they're much more predictable (fewer surprising edge case bugs) and much much more maintainable.
The more I think about it, the more I think SwiftUI is inspired by Angular - two-way data binding and observables everywhere.
Two-way data binding makes for shorter demos, but it doesn't scale nearly as well as one-way data binding. I've found in SwiftUI the way state gets updated across components becomes very messy very quickly.
Jetpack Compose is definitely inspired by React, hooks and all. I much prefer working with Jetpack Compose for this reason.
I suppose it's a compromise; the lower you go, the more control you have.
I used to work on an app where we used the UI builder at the time (I forgot the name) at first, but my colleague asserted that building the UI in code resulted in a faster app, because (according to him) parsing and rendering the XML output took longer than interpreting the code. I don't know if he was right, but a while later Apple introduced devices with different sizes (iirc the iphone 5 which was a little taller and the ipad) and doing all the layouting became impossible.
Anyway when I rejoined later it was a (I believe) healthy mix of the UI builder tool and custom code for some graphic / coded elements (think a fancy progress indicator). I suspect it'll be the same for SwiftUI.
Apple has historically not cared about mid-level companies and above, and SwiftUI is just another example of that. Everything they do is geared towards absolute beginners / very simple projects, even Xcode itself becomes basically useless once you reach a certain level of complexity. I don't understand why they do that.
> Apple has historically not cared about mid-level companies and above
I wouldn't say that. I've worked for a couple of marquee corporations that did a lot of work with Apple.
They do things like assign direct contacts to larger corps. They don't really rely on their "popular" culture docs to support bigger companies.
It's pretty natural to use their popular front as an "onboarding" system for smaller acts, with the plan to integrate them more tightly, if they get successful enough.
That said, their App Store is quite restrictive, and can be a big fat pain to deal with; even as a bigger corporation.
Quite doable, though. I've released over 20 apps to the iOS/Mac App stores, over the last dozen years.
Source? I haven't heard of any large company with complex projects fully adopting SwiftUI in their main product and not immediately regretting it. Successful adoption seems to be achieved only if the product is really simple or when using it in a very specific / isolated place of their main product (also simple). Everything else is UIKit because SwiftUI sucks at complicated logic.
Because, compared to some modern layout systems, it takes longer (to put it lightly) to internalize the exact logic behind the implementation of all CSS properties and be able to simulate how they interact in complex UIs in your head.
Can you provide some examples of modern layout systems? I’d be curious to see what’s on offer.
I have experience with various iterations of UIKit’s auto layout, Yoga, as well as CSS and some Swift UI. I’ve found CSS to be considerably easier to work with, particularly when using flexbox and grid.
Outer
+---------------------------------+
| |
| Left Middle Right |
| |
+---------------------------------+
Everything should be vertically centered. Left should stick to the "left" of the outer div, "middle" should be centered, "right" should stick to the right. Left/middle/right can have different widths and heights.
In AutoLayout this is achieved by 6 constraints:
- left.left = outer.left
- left.centerY = outer.centerY
- middle.centerX = outer.centerX
- middle.centerY = outer.centerY
- right.right = outer.right
- right.centerY = outer.centerY
I'd like to see how you implement it in CSS. (note: extra wrapper divs are not allowed)
Chrome just added CSS Anchor Positioning this year. The other browsers also expressed interest in implementing it, with Firefox having announced an Intent to Implement. The feature would likely be available on all major browsers sometime next year.
No. You're hardcoding the item widths in `grid-template-columns`. The left/middle/right items should be self-sizing. E.g. consider three divs with arbitrary text content.
Grid allows minmax(a, b) to specify the bounds of tracks. Possible values can be the remaining free space in the parent (fr), or the size of the content in the child.
But this does not keep the center col exactly centered, but it does allow the content to take the free white space and then wrap when needed.
In your original post with Swift, what happens?
I am not familiar with auto layout so I do not know the exact behaviour vs CSS. Do you have a few screen shots of how it would handle different sized content?
But now you just added `whitespace: no-wrap` to the middle element, with `overflow: visible`, to force it into a single line. That's hardly a generic solution, because it makes assumptions about the contained items... i.e. applying `whitespace: no-wrap` and `overflow: visible` will typically break the appearance of things.
Regarding AutoLayout: the six constraints from my original comment, don't say anything about the relationship between the left/middle/right items, so they will simply overlap if there isn't enough space. This can be remedied by adding two extra constraints:
1. left.right < middle.left
2. middle.right < right.left
It's just a bunch of equations. No weird tricks, no special cases, no hacks. You describe what you want with equations, and the solver spits out the solution.
Either put left, right as absolute (like the following) and leave middle in the flex, or do the opposite. One may decide which option to use based on whether the centre or the left/right is more semantically important in the layout.
We did have to use some CSS "tricks" (transform for absolute centring), but once you've learnt those then CSS is indeed quite sane.
outer {
flex-direction: row;
justify-content: center;
align-items: center; }
left, right {
position: absolute;
top: 50%;
transform: translateY(-50%); }
left {
left: 0; }
right {
right: 0; }
(This kind of layout, which is common in eg top nav bars, is slightly deceptive.
robin_reala's solution does not conform to requirements that left and right can be different widths, which would cause middle to be not centred under simple justify-content: space-between.)
Which underlines the original point, that CSS is a hodgepodge of different ideas with no overarching system behind them. A simple task like this needed 3 different positioning systems:
1. flexbox for positioning the middle item
2. absolute positioning for left/right
3. and the translateY(-50%) trick for vertically positioning the absolute positioned items
Touché. Indeed, CSS forces one to recognise layouts that may not conform to a layout 'flow' in boxes.
In its defence, I suppose recognising this is important, as to make potential box overlaps explicit (which is typically unwanted).
CSS also handles a whole lot of things other than layout, which I'm not well informed of layout constraint systems being able to handle. Being a hodgepodge is an advantage, comparable to how its a great advantage that one can invoke any hodgepodge systems task from bash, as one single tool.
Wrong. `flex: 1` will cause the items to have a max-width of 1/3rd the container width. E.g. if the left and right items are small icons, and the middle one is a longer text, then the text will be forced to wrap into multiple lines as soon as it tries to grow beyond 1/3rd of the available space, even though there's tons of wasted space on the left/right.
I really like the fundamental ideas of SwiftUI, and want it to work, but have found that it doesn't allow me to write the kinds of apps that I like to release, so I still use UIKit/AppKit for my shipping apps.
The documentation for SwiftUI (and most new Apple SDKs) is awful. It's clear that they are relying almost entirely on inline code docs. They used to have a legendary documentation team.
Inline code docs can actually work quite well (I do it, myself[0]), but it requires serious discipline. If you cloc my codebases, it usually comes up 50/50 between docs and executable.
I liked Paul Hudson's Hacking with macOS (https://twostraws.gumroad.com/l/hwmacos) which includes an older AppKit edition of the book. You'll have to account for changes in Xcode since the book was published. Also, there's a chapter that uses the now-defunct Dark Sky API but you can replace it with Pirate Weather's API which is 1:1 compatible.
There are probably a lot of resources and tutorials out there for learning the UIKit-Swift combination. For AppKit, on the other hand, most of the best resources are "old", which means they were written before Swift was introduced. Thus, if you want to learn AppKit, you probably want to learn Objective-C too.
You can of course write AppKit-Swift code, and many AppKit developers do. However, these AppKit developers learned AppKit-ObjC first and only later switched to Swift. I'm not aware of a lot of AppKit-Swift learning resources.
I’ve been learning AppKit-Swift to build my own screenshot annotation app, mostly using StackOverflow and reading Apple’s older docs which are all ObjC. There’s very few things that don’t translate 1:1 from ObjC to Swift with the same API names. As long as you know what a message-send function call looks like in ObjC, you can read such examples and apply them to Swift.
ObjC: [[FooClass alloc] initWithFoo: foo and bar: bar]
I’m working on a moderately complex iOS and macOS app in SwiftUI. I haven’t tried the new stuff yet but it’s definitely a very mixed bag. It can save you a lot of time vs the old APIs for simpler things but it can make hard things even harder.
And you’ll probably find yourself dropping down to UICollectionView and NSCollectionView for performance. Xcode remains a terrible IDE.
AutoLayout is a good example of the last generation of Apple APIs. Even the easy things are painful but if you need to do something really complex there's a way to make it work.
Right now I'm stuck in a situation where any SwiftUI widget except for List has terrible performance but List imposes all these other constraints I can't live with so it looks like once again it's back to UI/NSCollectionView for me.
> Warning: there’s a bug right now that crashes the app in macOS 15.1. […] I’ve tested this with Xcode 16.0 beta 6 and Xcode 16.1 and they both act the same. But on a computer running macOS 15.0 beta 7 and Xcode 16.0 beta 6, it works perfectly. So this is a bug in macOS 15.1.
One of the reasons I've left development for the Apple ecosystem is that these things happen all the time. They are tedious to fix and often require reverse engineering their system.
There is also something to be said for being a developer in an ecosystem that is actively hostile towards you and your interests as a software developer.
It looks a lot like Stockholm syndrome from the outside at least.
But I genuinely don’t understand how or why anyone would pick up native iOS / MacOS development in 2024. It seems like an incredibly shit medium to long term bet.
My reason is that frameworks are generally more wide and deep than can be found elsewhere. It’s not difficult at all to build a polished app with nothing but Swift and AppKit/UIKit, with few or no third party libraries, which is increasingly rare in my experience (certainly not the case with WinUI or Android Framework). The next most comparable thing is Qt Widgets, but that’s for practical purposes restricted to either C++ or Python and is seemingly not receiving much attention any more than it’s been decided that the more “bring your own everything” style Qt Quick is the star of the Qt show.
AppKit/UIKit aren’t afraid to be opinionated either which is occasionally annoying but 90% of the time a good thing, because that makes for tested and supported happy paths that work well. Android Framework is the biggest contrast here, being littered with multiple half-baked ways to do everything, none of which Google has shown any particular preference toward until in just the past few years.
What would get me to move for my personal projects is something with that solidly “batteries included” aspect to it (there’s no excuse for needing to rope in a third party library to get something as mundane as a scrolling sortable table view with headers in a desktop UI framework, that’s like new cars coming without wheels) and similar opinionation, along with support for Swift or compiled Swift-like language.
I dunno about MacOS but iOS is a potential market of billions of users; for that kind of market people are willing to eat a lot of shit sandwiches. And there's plenty of markets where the development tools are much, much worse.
Until you're not allowed to anyone. You get the higher risk and higher reward with them and just have to hope they're not looking at your app specifically today.
Code complete using the older APIs is a disappointing. As only a casual Swift dev, one of the hardest things to get a handle on is the myriad of ways there have been to do things in Swift and Apple frameworks over the years. The online community is amazing at writing articles and making up for Apple’s shoddy docs but I’ve got down a few paths recently that were “the old way”.
I was really hoping their version of CoPilot would help with this but, unless this is just beta bugs, it looks like that’s not the case.
Between lack of examples on SO and the API changing recently, copilot is simply left behind these days. We may get a better help for today's features in a year, when enough posts and projects use them.
The moment I start doing any development in the Apple ecosystem, I immediately perceive complete and utter contempt from Apple - coming from the extreme constraints placed upon me as a developer, from the requirement of using sadistic tooling, and from the lack of documentation and absence of engagement with the community in their forums.
I get the distinct impression that Apple will begrudgingly allow me to develop and market a commercial tool, provided I pay them for the privilege, and that they very much hope that someday they will be able to rid themselves of third party developers once and for all.
As someone who works with both Android Studio and Xcode, I could say AS is lightyears ahead of Xcode.
Gemini on AS is so good and most of the time accurate and adopts to how you name your variables and functions. Xcode 16 on the other hand, what a shitshow.
Agreed, every time I open AS to update my company's Android apps (infrequently) I have to spend an hour Googling odd Java memory errors and grade sync complaints before I can do the minor tweaks I need to do to the actual app.
Also prefer Xcode. As long as you stay away from XIBs and Storyboards it’s more responsive than Android Studio.
And yeah, if you let a project lapse on gradle and library updates for any length of time at all be prepared for a fight to get it all brought back up to speed. Swift Package Manager is generally less of a headache.
Some of AS’ “smart” features are also more of a hindrance than a help at times, and don’t even get me started on ProGuard (which has no Apple ecosystem equivalent).
Also. That said, autocomplete outside of Xcode is way more accurate. The latest beta predictive code is even worse than what we had… hallucinates APIs for the most vanilla of Foundation calls. Half my reflexive autocompletes now turn into — wtf I accepted this junk AI idea?
With the exception of the instruments features, Xcode’s poor refactoring features, needless animations, bad code navigation, lack of a terminal, and limited plugin support make it such a drag to use. AppCode was better in almost every regard but was discontinued.
My biggest problem with Xcode is that it really only works for Swift, while the Jetbrains stuff (incl. Android Studio) works well for a lot of languages.
The pattern it enforces is theoretically great, but you will get much more mileage out of learning to write in a "reactive" style manually (When state changes, update view to match. It doesn't need to literally be a function of state to make it a function of state. E.g. don't leave ifs without elses.)
A perfect combination would be a SwiftUI-style UI editor (sans bugs) to define UI, constraints included, but traditional layout management at runtime. Well, that or a ground-up redesign of SwiftUI's API.