21 ms·
30k lines of SwiftUI in production later
- politician 4y agoGiven that a predominant paradigm in apps is the infinite scroll view that receives updates, it’s a tragedy that SwiftUI does not ship with a rock solid implementation and instead succumbs to jitter and scroll-into-view issues.
- dmitriid 4y agoWhat amazes me is that scrolling has never really been an issue in any native app? And yet here we are in 2023, with a native framework built for modern devices (where scrolling is the main interaction) that... inherits the worst behaviors of web of all things?
- tempodox 4y agoMy thoughts exactly. With the problems reported in the article, I wouldn't want to use SwiftUI, no matter who else declares it “ready for production”.
- avianlyric 4y agoI think scrolling has always been an issue with native apps, it’s a fundamentally hard problems to solve on CPU and memory constraints device (although modern phones are neither). Scrolling allows the user to move through huge amounts of data in a very short period of time, loading that data in, rendering it, then animating, all at 30-60fps is difficult. 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).
- geraldwhen 4y agoUiTableView could use arbitrary height cells and smooth scroll a decade ago, as long as you could compute row height. UiScrollView has always been harder to deal with.
- mrtksn 4y agoI don't think this is true, I recall an interview with the original Instagram people saying that it was not possible to scroll with that many photos and text being live rendered and they had to fake it with something like pre-rendering the UI as an image and scrolling that.
- hombre_fatal 4y agoScrolling has never been trivial. It’s very hard to build abstractions around it. For example UITableView required quite a lot of boilerplate and manual edge case code. Android’s abstractions have very similar issues. 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.
- jb1991 4y agoScrolling is hardly a solved problem. On iOS, for example, using UIKit which is very mature and performant, to avoid performance issues with a scrollabe table of, for example, thousands or tens of thousands of items, you use an api that recycles UI components to support lazy loading and the lowest memory usage possible in such a scenario. If you jump in to do this naively, it will destroy the user experience and the battery as your device will doing orders of magnitude more work than necessary. You don't encounter lists of this length as often on web apps, but the same issue would apply if you did -- why do you think infinite scrolling only loads a few rows at a time until you scroll further? And how many times have you been on an "infinite scroll" web and as you scrolled, you had to wait for it to do the work for the next scrollable content. Happens to me often. Now take all those concerns and bundle them in a UI that is suppose to manage all this for you automatically via declarative behavior, and you can see why it's not as trivial as you suggest.
- WA 4y agoDescriptions like these makes me wonder how we ever made a single computer game with millions of polygons that are in view or not and must be rendered accordingly.
- jb1991 4y agoWell at least what you describe would be sitting on a GPU using all the technologies (both hardware and software) developed for precisely that purpose. 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.
- avianlyric 4y agoCompletely different problem. Rendering millions of polygons is almost trivial to parallelise, and there’s plenty of hardware around that’s capable of providing the needed parallel compute. You’ll note that games have loading screens, those exist so the games can get everything it needs into working memory, order it to enable extreme levels of parallelism. And only then do you get buttery smooth 60fps, and games, of course, stutter and jump if they need to dynamically load new content in, but can’t quite get it into working memory before it’s needed for rendering, usually resulting in entire frames being delayed. 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…
- veidr 4y agoThat isn't true; scrolling (and resizing) was a performance sinkhole for all kinds of apps that used the native table views (NSTableView and NSOutlineView), for many generations of Mac OS X. 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.
- Pulcinella 4y agoScrolling on SwiftUI is extra bizarre because I often observe weird micro stutter. A scroll view with perfectly static text that never updates will sometimes scroll at what seems to be ~45fps. But really it’s more like it’s randomly dropping 1 out of every 4 or 5 frames or so. It also seems to be related to dragging the scroll view, because programmatic scrolling can be very smooth. (Also SwiftUI was weirdly capped at 60hz and couldn’t do 120hz until iOS16.2. Doesn’t make me confident that SwiftUI will ever get a lot of development love from Apple if it took over a year for SwiftUI to support a flagship feature from the iPhone).
- jalino23 4y agoI also fell in love with swift when I had to learn it trying metal. it just succs how you have to use xcode with it.
- silh 4y agoAFAIK, you can also use VS code or CLion.
- _corvo_ 4y agoI’m assuming you meant AppCode. It’s been discontinued: https://www.jetbrains.com/objc/ https://www.jetbrains.com/objc/ With VSCode, do you get live preview?
- StewardMcOy 4y agoThe Swift team released a VS Code plugin recently. As far as I'm aware, it doesn't do live preview, but considering how often Xcode fails to render live previews, I'm not seeing that as much of a loss.
- mrtksn 4y agoWhat's wrong with Xcode? Is it the usual "iPhone is preparing for development" type of annoyances? Is it the bugs that sometimes prevent you from compiling? Or is it something more fundamental like even when everything works fine you don't like it?
- parker_mountain 4y agoThe first, yes. The second, also yes. The third, also, also yes.
- mrtksn 4y agoOkay, can you give some details on what's wrong for you? Like what is the better way to do it?
- layer8 4y ago> we wanted to move our entry UI to open in a sheet and with immediate focus on the title TextField, but there’s a noticeable delay before the keyboard pops up. So we didn’t. > 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.
- newZWhoDis 4y agoSomething else is going on, I have no such delay with @Focus set onAppear { }
- Swalden123 4y agoI agree, in latest swiftui versions what they want is possible. The same with the keyboard opening and closing when pressing next. There’s an issue elsewhere
- sdfjkl 4y agoTo me that seems like an incredibly huge amount of code for an app user interface. Turbo vision certainly was much more efficient, or even wxWidgets.
- DelightOne 4y agoTLDR: 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.
- jamil7 4y agoEvironmentObject is a total foot gun for performance and causes a bunch of other issues. Core Data and SwiftUI are also awkward together. We ended up keeping Core Data at arms length and building our own internal framework to do dependency injection.
- newZWhoDis 4y agoThe trick for 1) is to use @Observed object on a state class inside your app struct then push to views via @Published combine streams so you can map/filter/reduce. Storing massive state in every view/child view/grandchild view is both stupid and wasteful. 2 and 3 I can’t reproduce.
- DelightOne 4y agoYep! I currently use Composable Architecture for the same purpose.
- akmarinov 4y ago2 and 3 are fixed in iOS 15+
- ec109685 4y agoThis Equals behavior seems terribly unintuitive as well: https://swiftui-lab.com/equatableview/ https://swiftui-lab.com/equatableview/ When an object contains plain data, the equals interface is not used. That would so rough to debug the first time.
- abiro 4y agoSwiftUI and UIKit compose well in both directions, so if you choose SwiftUI as your framework, but then run into a wall, it's an option to partially rewrite that difficult part with UIKit. 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.
- GeekyBear 4y ago> It could — and really should — have been easier, especially considering SwiftUI has had three major updates since it was announced in 2019. 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.
- LudwigNagasena 4y agoWhy is it overoptimistic? It’s the same company, they should be able to leverage their past knowledge.
- lapcat 4y ago> It’s the same company, they should be able to leverage their past knowledge. 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. https://en.wikipedia.org/wiki/Ship_of_Theseus https://en.wikipedia.org/wiki/Ship_of_Theseus
- LudwigNagasena 4y agoI guess that means we should expect AppKit and SwiftUI to never improve.
- lapcat 4y agoAppKit has been going downhill for years.
- StewardMcOy 4y agoI don't know why this is being downvoted. The situation is more complex than this simple comment, but the sentiment is correct. 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.
- bsaul 4y agothe worst isn't mentioned : not only is swiftui causing all kinds of glitches of it own, but despite being a brand new framework, it still locks you 100% to apple devices. 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.
- toyg 4y agoWhat missed opportunity, Apple saw the opportunity right there and took it: the opportunity to reinforce the lock-in they always, always consider imperative to achieve. 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.
- bsaul 4y agoi know, it's just completely delusional. 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.
- cellularmitosis 4y agoThis thread is either completely serious or completely sarcastic and I love the fact that I honestly can't tell which it is :)
- bsaul 4y agoI was quite serious :)) why do you think it's sarcastic ?
- kitsunesoba 4y agoSwift is in considerably better shape than Obj-C is when it comes to cross platform. It’s not perfect, but it’s at least usable (there are production back ends written in Swift for example), it’s been slowly getting better, and Apple recently committed to filling many of the holes/inconsistencies in cross-platform with their announcement to rewrite Foundation in Swift and make it open source. 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.
- SpaghettiX 4y ago> It took a few hours to fall in love with SwiftUI. > 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.
- jb1991 4y agoThe problem with solutions like Flutter is that many apps, especially iOS apps (though maybe not a calendar app), will often use powerful platform features on iOS that are not so readily available on other platforms, so some degree of platform-specific code is always going to be there -- maybe a lot of such code. For example, the amazing Core Image library, or writing Metal kernels (increasingly common since it is rather easy to leverage GPU compute on iOS and offers tremendous performance benefits), and other tools. If you are going to interact with that in Swift anyway, adding a new language and UI framework and extra layer of abstraction and communication to your app may not make sense.
- sgt 4y agoAs a Flutter developer, I am 100% aware that native is usually best, unless you are writing Android apps which are bit of a nightmare compared to iOS.
- rickspencer3 4y ago
- pictur 4y agoIs it possible to write an application of this scale with flutter without (or very little) infecting swift? probably can be written, but I would like to hear comments about what can be experienced in terms of performance and development.
- newZWhoDis 4y ago30k LoC is not a particularly large app. I have SwiftUI apps in excess of 100k LoC and plenty have larger than that. Just my 2 cents.
- jb1991 4y agoI love declarative UIs and still long for the days I was writing early front-end React apps nearly a decade ago and how amazing it felt for a UI to behave that way. Years later, today I work primarily in iOS and would love to do this on that platform, but every time I read an article like this, my head hurts. Workarounds for workarounds, a great many special cases that are quite unexpected. I've gotten very fluent with UIKit and doing all sorts of custom controls and animations, and to abandon that comfort and productivity for another...year?... of a frustrating learning curve does not entice me to give it a try. 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.
- newZWhoDis 4y agoYou won’t throw any of that away, you can structure your app around SwiftUI and drop in to UIKit for custom controls whenever you want. This is a good idea for MapKit and web views at the moment, and probably the camera.
- nodemaker 4y agoOr you can structure your app in UIKit and build custom views and nice animations in SwiftUI. SwiftUI is a nice abstraction but a lot of it is really unnecessarily force fed by Apple because it helps them get more amateur developers into the platform.
- StewardMcOy 4y agoIt's a great solution when it works. MapKit and web views are good examples of it working well, but it can get buggy with anything more complicated, especially when mixing Views and UIViews in the same parent view. The worst part is that the behavior can change based on the OS version. You have to be proactive with testing your apps on the beta OS releases ASAP. 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.
- lawgimenez 4y agoI think the author was just pushing the boundaries of iOS development too much. You could tell in the app that the UI was complex and some guidelines were not followed. This is the consequence when you over engineer and over design and being fancy.
- nodemaker 4y agoNative platform development is about going as smooth as possible. Otherwise React Native serves very well for mediocre quality stuff.
- meindnoch 4y agoWhy can't people just use boring technology?
- herodotus 4y agoThis is why: it's hard to get things right. When I started programming for Apple almost 20 years ago (mainly using Objective C), too many hours of my time were spent making sure that I was dealing with memory correctly. Easier in Objective C than C's primitive malloc/free, but still hard, even with the tools to help. During my time there, new things were tried: firstly garbage collection, and then automatic reference counting. This last got rolled into Swift, and hours spent looking for memory leaks or dangling pointers become a thing of the past. It is still possible to have memory problems in Swift, but mostly they can be avoided. 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.
- nodemaker 4y agoFor an expert with some mathematical intuition layout constraints can do a custom layout that lays out perfectly on all screen sizes much better than declarative. However there is a learning curve I admit.
- Pulcinella 4y agoI love AutoLayout constraints…unfortunately Apple has never improved debugging tools. So when the system breaks and spews a bunch of autolayout constraint complaints to the debug console, it can be difficult to determine what went wrong (especially because the system will sometimes generate its own constraints, like if you are using stack views, and you have no insight into why they were generated or why the system is ignoring and discarding the constraints you made). 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.
- fieryskiff11 4y ago[dead]
- LeicaLatte 4y agoSwiftUI is the web3 of the iOS world.
- nodemaker 4y agoHaha couldnt have said it better.
- nodemaker 4y agoHow does everyone feel about hiring iOS devs in this environment? I feel like its too hard for SwiftUI devs to pick up UIKit when they get blocked and usually they just give up. Also in interviews junior devs have no clue about AutoLayout or UICollectionViews.
- deleted 4y ago[deleted]
- akmarinov 4y agoI don't know of anyone that calls themselves an iOS dev and doesn't know any UIKit. 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.
- cutler 4y agoAnother to reason, if one was needed, to leave iOS development well alone if you value your time.
- breatheoften 4y agoAside from any quirks in the rendering model -- at a more fundamental level I can't imagine what apple is thinking with the observable object data modeling approach -- and what [seems to be plans](https://forums.swift.org/t/pitch-observation/62051 https://forums.swift.org/t/pitch-observation/62051) to expand it ... it feels like the ObservableObject style modeling approach has been tried a million times in various frameworks and always results in complex and difficult to debug systems -- codebases which make it inherently incredibly difficult to reason about "what happens when this data changes" A Unidirectional flow + data flow-like solution makes so much more sense to me as the basis for sane data modeling for ui's ...