30k lines of SwiftUI in production later
blog.timing.is
blog.timing.is
> It was in development for 12 months. It would have been less if SwiftUI just gave.
> At the end, we didn’t drop it for a couple of reasons. We were too deep into the process. Being a bootstrapped operation that was already severely behind schedule, we couldn’t afford to restart.
This may be useful to someone trying to create something:
In terms of software engineering, you took "a few hours to fall in love with SwiftUI." There could've been more evaluation done: reviewing existing complaints of SwiftUI, implementing the most challenging parts of your UI as a sanity check, or trying it in a small side project, hiring a developer that has used it before, etc. Also, why count lines of code, as opposed to describing features and challenging technical details. Lines of code doesn't signal anything (e.g. effort, quality, time spent, features, is it code generated?, etc.). Every line is an extra source of bugs.
In terms of product development, it took 1 year to ship the product, so after all that, you don't know if you have customers. That's fine for a side project, but this is a "bootstrapped operation behind schedule".
Alternative: I hear Flutter is quite productive. If you one to fall in love with technology, you'll like Flutter.
For this application, it sounds like the underlying services are not very platform specific, so on that level it seems like Flutter is a good choice. My concern would be that the developers seem very focused on the quality of the experience of even micro-interactions. My experience in Flutter would say that this degree of attention to detail would be hard to get right with Flutter, especially without choosing a platform to focus on, in which case the cross-platform benefits of Flutter are minimized.
Whether delaying an MVP for months to achieve that quality in the user interactions is an interesting side debate, though.
Native devs are going to make a lot of money rebuilding apps for companies foolish enough to base their entire company on a Google “product”
Not all apps require 120fps performance either, mine was just buttons and feedback from the backend.
Flutter was actually perfect for this application.
How are you supposed to do this if you don’t yet have proficiency in the language/framework/toolset?
React Native has 1000s of people with experience in React, with experience in JavaScript/Typescript. There's people with 10+ years of experience.
There's a very small percentage of Flutter devs, since Dart is barely used in Flutter. It being very knew, there's almost no one comparatively.
If you're a company and go with Flutter, you'd be constantly trying to find people for your project.
Even if Flutter is 2x as faster to write code for or 2x as performant than React Native, etc - it doesn't matter if you can't find the people to scale and churn.
Then there's the whole "when will Google kill it" with them doing Flutter and Jetpack Compose and then there's also Kotlin Multiplatform (not from Google), it seems like they're a layoff away from shutting it down.
You know Meta will keep React Native around for decades, since a lot of their stuff is built on it.
> when you are editing an entry, we want the title field’s cursor position to be at the beginning. But, alas, not possible.
That such basic functionality is not possible is astonishing. Especially the first one should be a common use case.
But I love the declarative paradigm so much; if only I could easily bring in my toolset of choice, whether it is Elm, Redux, etc, with all the power that native controls on iOS have, that would be awesome. SwiftUI is the only valid answer, but wow, I cannot get motivated to go down that rabbit hole.
This is a good idea for MapKit and web views at the moment, and probably the camera.
Also, and this might have been fixed already, but a couple years ago, there were problems getting updateUIView to run in response to ObservableObject updates.
The promise of UIViewRepresentable is a lot like SwiftUI itself. It's great when it works, but there's little you can do when it doesn't.
Time for the obvious question: Why not React Native?
2 years on, their RN devs can't get the app to compile with M1 macs, so they all use Intel macs. They can't update to a recent RN version (recent, not the latest), because a RN navigation library has an issue with it and they're just sitting around, waiting for someone to fix the open source library...
I could go on with the multitude of dependency hell issues they're having.
It's a huge pain.
I mean I guess that’s sorta what React Native does, so it must be.
Apple (and Next) have been iterating on AppKit for three decades. The UIKit fork of AppKit for iOS is a decade and a half old.
Expecting the same level of polish in SwiftUI after three years is a bit overoptimistic.
Apple has said that SwiftUI is "where the puck is going" so you can expect that they will keep on iterating on it for many years to come.
It's not the same company. Compare 2023 to 2003. Different CEO, mostly different leadership (only Eddy Cue and Phil Schiller remain), massive employee turnover and new hiring. Even the name is different: Apple Inc. vs. Apple Computer, Inc.
The reality is that AppKit has had its ups and downs recently. There are obviously people in Apple trying to do their best to patch things up, and there have been some nice improvements because of their efforts, but some really bad bugs have been introduced, only to sit unfixed for years. It's gotten to the point where I dread the yearly OS updates, not because I dread having to update my code, but because I worry what has broken.
In my experience, if you don't get your bugs filed within the first week after WWDC, they'll never get fixed, and even if you do, it's a toss-up. But testing your existing code isn't always enough. If you're writing new code to take advantage of some of the new OS features, you can be a month into the beta cycle before you find a bug, and by that point, its too late.
Quite the opposite. I would argue that macOS (the artist formerly known as Mac OS X) is quickly being transformed into iOS. Big Sur was a massive change in this respect, and the transformation continues in Ventura.
UI wise at best it's some paint. The port of Stage Manager is horrendous as well.
Freedom wise I find it just about still tolerable. You can still run non-blessed binaries after some hoops and access a good amount of APIs.
Sorry, but it takes time for new things to gain functionality and polish. Windows RT was from 2012, and running x86 software on ARM only became possible recently.
>I’d have only Slack open, and switching between channels would still take almost three seconds (yes, I timed it on my phone). Spotify, also with nothing in the background, would take 11 seconds to open, then be frozen for another four seconds before I could finally press play. When I typed in Chrome, I often saw significant lag, which led to all kinds of typos (because my words weren’t coming out until well after I’d written them). I’d try to watch YouTube videos, and the video would freeze while the audio continued. I’d use the Surface Pen to annotate a PDF, and my strokes would either be frustratingly late or not show up at all. I’d try to open Lightroom, and it would freeze multiple times and then crash.
It quickly became clear that I should try to stick to apps that were running natively on Arm.
https://www.theverge.com/23421326/microsoft-surface-pro-9-ar...
[1] https://compose-web.ui.pages.jetbrains.team/
[2] https://github.com/JakeWharton/mosaic
[3] https://github.com/fgiris/composePPT
That’s a problem because they stopped building Swift into third party app packages a few years ago in effort to bring down app download sizes, but that means that apps have to deal with whatever version of Swift comes with the user’s system.
The best middle ground would probably be to ship Swift as a periodically updated package.
For example: You can't debug IOS 14.5 apps on Big Sur because Xcode for some reason needs Monterey. Though if you just spoof the required version in the xip's app manifest it'll work mostly fine.
Is it?
Should I expect my M1 macbook to break in unexpected ways for a decade before it works too? M1 is new, like SwiftUI is new, how come it actually works?
Apple devs have stockholm syndrome.
Leaks of Apple doing test ports of MacOS to it's ARM chips dated way back to 2011.
So, not new at all.
Of course if the problem is with the core of your application like the scrolling example in the article, this is not going to help you much.
I mean, i had hoped that with a declarative UI apple would at least create some kind of path to web or android renderering, making at least part of the code reusable somewhere. But no, still 100% lockin. Which to me is a HUGE missed opportunity.
People think Apple simply don't care about other platforms, but that's just not true. They do care - they care that developers should stay the hell away from them.
Thinking that a programming language can thrive in a walled garden is insane. They've been burned by this in the past with objc, i don't understand how they can try again.
By contrast, Obj-C couldn’t even allocate memory without the assistance of AppKit, UIKit, or GNUStep. On its own it was woefully incomplete.
As for UI frameworks, porting SwiftUI would be a tall order with how it’s partially built on top of AppKit/UIKit. The most we’d probably get if it were open sourced is the surface bits, not the underpinnings.
Unfortunately all those options got cancelled, and now apple remain on its own using it. I don’t believe in cross-platform swift anymore.
A programming language thriving is a secondary or tertiary goal.
I don’t think swift has any future in the long term unless they go multiplatform.
They just don't care. Apple will do what Apple will do.
LOL!
Any other vendor: Big maybe (Microsoft figured out a few iterations late that it might help against being left behind). Apple: Of course not.
Even for their cross-platform services they'd rather make the same app twice than accepting even a 20% higher likelihood that iOS apps also get released on Android.
A Unidirectional flow + data flow-like solution makes so much more sense to me as the basis for sane data modeling for ui's ...
1) Don't watch too much state with Observable/EvironmentObject. When any watched property changes EVERYTHING RELOADS every time.
2) ScrollView.scrollTo is bugged with ForEach.
3) TextField and keyboard-interactions can be slow and buggy.
2 and 3 I can’t reproduce.
When an object contains plain data, the equals interface is not used. That would so rough to debug the first time.
In the case of UI, use of a library is essential. And of course boring technology has libraries. But the real problem is layout: not just where your elements sit on the page, but where they go after the user resizes a window. In the early years, this was not too difficult because screens were mostly fixed size and in landscape mode. But now there are many aspect ratios, four possible orientations and so on. Apples earlier solution was a system called Layout Constraints. Frankly I found them really difficult to use, even when I stuck with the ones provided within Xcode. SwiftUI seems to me the exactly correct way to deal with layout complexity. Admittedly lots of it needs to be improved (as the article points out), but I would much rather use a declarative approach to layout than any alternatives I know of.
Apple’s documentation has also gotten way, way worse. Apple expects you to watch the WWDC videos, but it’s not like they make refresher videos on old topics all the frequently and they often remove or hide old videos.
And yes StackView is your biggest friend. Usually when the system ignores your constraint it says that on the log. It can be a bit tricky to find out which constraint its breaking but the View Debugger and also the constraint constant value can help find it.
Eventually I tried going back to manual layout because a coworker still used it all the time and I noticed that it was pretty easy to follow the layout rules in imperative code (so long as it's well-structured). Since then I just do manual layout for everything. It's just easier for my brain to describe the layout I want that way. I feel like it takes me longer to come up with constraints that match what I want, but I'll admit if I went back to auto-layout, I'd probably be better at it.
The reason I suspect people don’t think scrolling was ever an issue (especially on iOS, I doubt Androids will share the same view), is because Apple spent so much time getting it right for the original iPhone. Correctly identifying that scroll behaviour was a kind of “killer app” for touch screens.
But in order to make that scroll behaviour so rock solid. They heavily constrained the problem and did bunch of visual tricks to make it appear smoother that it actually was. Most notably, native scroll views generally required that every individual scroll element was an identical size and shape. So you could cheat during the scrolling process by not actually rendering all the content while scrolling, just rendering the UI chrome (which was identical for every scroll item), and loading the content once the scroll velocity was low enough that there was time to load and render the details before they needed to be displayed.
The other thing that happened, was basically stopping any other compute from occurring. When you scrolled on the original iPhone (and for many generations afterwards), your phone basically dropped everything and dedicated all its compute to just scrolling the view. Not even code to compute the content of scroll elements was executed, you were expected to have done that before the scrolling started. This was most obvious in Safari, where JS execution was halted, and even page rendering was halted, so if you scrolled beyond the boundaries of what had already been rendered, you just got white.
With modern frameworks (and especially the web) there’s been a strong desire to deliver scrolling with a completely arbitrary set of scroll elements, that can all be different shapes, sizes, colours and trigger all manner of background computation. Modern devices are broadly capable of delivering that, but care is needed to exceed the available compute. That’s different from historical native frameworks, where they simply didn’t let people have that kind of flexibility. You got the handful of options the framework gave, and that’s it (which is why older iOS app all had identical scroll UI).
UiScrollView has always been harder to deal with.
So no, it’s never been a solved problem just like UI abstractions have never been a solved problem, so solved that there’s nothing to improve or explore.
Also keep in mind that the battery drain using those technologies to play a game does not scale to a normal mobile app when people expect their phone to be available all day.
Scrolling on the other hand is a very sequential task, if you don’t want to have a loading screen before displaying the list. The location of every item in the list depends on the location and size of the item before it, those data dependencies make parallelism pretty close to impossible. Made worse when each item is loaded on demand, and needs to execute code to determine how it should be rendered.
Of course, you could load all your scroll data into memory, precompute all the needed render parameters, arrange the results for parallel rendering, then have blazing fast and stable scrolling. Just like a video game loading screen, but then every scrollable view would have a loading screen…
It is not a big ask to have a scrolling UI. Look at motif from 80s.
It is a solved problem, the solution is load things lazily as needed, and the UITableViewDataSource protocol is one template you can follow for doing that.
> using UIKit...you use an api that recycles UI components to support lazy loading
They eventually added enough optimizations and performance cutouts to make it pretty easy to not fall in the hole with your app, so it hasn't been a problem with AppKit (or its younger 85% clone, UIKit) for a long while.
But I'm not surprised to hear Apple's much newer and not-very-related UI toolkit still has lots of those problems. That's one of the problems when not many developers actually use a technology — it's not just a popularity contest, having lots of users who complain is how you find a lot of the bugs and performance issues in your UI toolkits and app frameworks.
So lack of popularity often does mean there are probably a lot of those.
With VSCode, do you get live preview?
The second, also yes.
The third, also, also yes.
It has all sorts of bugs and weird fail cases.
Honestly you should just search the internet for testimonials because anyone who uses Xcode can create a list of issues rather than rehash them all here in response.
So many features and linters and tools end up building a huge cognitive overhead, which is the primary reason I haven't been touching JS since a few years. The JS world piled up so me sh*t in order to make the working with JS something that is not, that I found myself not having energy and time to do something other that setting up tools and frameworks.
What I want is to be able to start coding like start writing an article in a Word document and Swift Playgrounds is getting there. XCode was good too but wasn't anything special, Swift Playgrounds is amazing.
I'm especially excited for WASM, so maybe I can just write everything in Swift eventually.
2) It's extremely buggy, like on a daily basis where something just doesn't work for any apparent reason that is usually either fixed by killing Xcode or removing derived data & then killing Xcode
3) Lack of plugins for even the most primitive of features like autoformatters
4) XML for build configs inside .xcodeproj
5) Why does it take half a day to update through the App Store?
I mean it has some nice features functionality-wise, such as the metal debugging toolkit, but the experience of actually coding in it is abysmal. Like so bad that I've been doing as much of my Swift work in VSCode as possible, which Xcode actually prevented for a while due to a bug in how it handled local Swift packages.
The bugs can be annoying but they usually go away after restart and cleaning the junk.
> 5) Why does it take half a day to update through the App Store?
But this one is really annoying. Also for some reason in downloads and installs TWICE.
2) yes
3) I don't really use plugins in IntelliJ either - I do in VSCode but only because it's pretty useless without them
4) Not sure what the problem is with this, but I will say I prefer Package.swift projects for anything that isn't targeting a UI runtime
5) App Store update process just doesn't play well with 8GB applications. Either delete it and re-install from App Store or use something like Xcodes.app
Although I miss github copilot a bit when I do it.
SourceKit can get really grumpy with things like deeply chained optionals, deeply nested blocks, and lots of casting or otherwise fighting against the type system. Not doing those things makes it run significantly more smoothly. So if Xcode starts bogging down or SourceKit is crashing, it means there are probably cleaner ways to write whatever I’m currently working on.
I still have no idea how I can quickly switch back and forth between open files. Either the feature is entirely missing, or completely unintuitive to discover and/or use.
For the record, I am writing this message in 2023.
These days I typically use cmd-control-left/right to navigate the open file history and then cmd-shift-[/] to navigate open tabs.
Also worth noting that you can find these in the Navigate menu if you want to peruse all the options.
It’s extremely slow on high-spec MBP.
It sometimes takes developers over 14 hours to update.
It interferes with other command line tools, forcing itself into the middle — if you’ve ever tried to run git on a fresh MBP and run into the xcode-select install step, you know this one. It’s a bad citizen.
Installing XCode will cause a perfectly functional machine heavily used for development in VSCode to experience several full crashes until it fully takes over the machine. MacOS with and without XCode appear to be two fundamentally different operating systems.
Having XCode running for any amount of time saps battery like nothing else. You can run VSCode for 24 hours on a MacBook Air with M1 for maybe 3 hours in XCode.
The git integration is so utterly crap and broken that it’s safer to turn it off rather than fighting the secret intermediate repo cache that it hides from you and sometimes forgets to update.
For some idiotic reason, creating a new file in XCode prepends the file with a comment block including the name of the file, the date, and the name of the user. Who asked for that? For a file that’s part of a repo that’s going to be touched by multiple people over a long period of time and likely renamed, this is just obnoxious noise.
However you might have some other issues with your system because I practically never close Xcode and I’m having like +10 hours of battery life on my M1 air. This includes actual work being done in Xcode.
I do regularly find that mDNSresponder has been sending and receiving 100’s of GB over the network and must be force killed. When that process goes off the rails, it also saps battery.
I wish that I didn’t have to keep Activity Monitor open at all times on both machines just to keep ahead of the problems. It’s not like effectively running top is cheap.
This is standard corporate policy at most/all big software shops. Apple uses Xcode internally, so the format and contents probably reflect their policy.
The block can be customized for your policies -- or removed completely, if preferred.
Like how would you do a WebView in SwiftUI otherwise? There's a ton of things that SwiftUI doesn't have that you need to go down to UIKit for.
Just my 2 cents.