3 ms·
I'm building an IDE in (mostly) SwiftUI, and have been using it since release, so I feel like I've worked with it more than most people. A couple observations:
by rudedogg 4y ago
I'm building an IDE in (mostly) SwiftUI, and have been using it since release, so I feel like I've worked with it more than most people.
A couple observations:
- SwiftUI is really complex
It's going to take you at least a year to get used to the declarative way it works, and be able to make UIs without struggling to figure out how to shuffle data around. If you look at SwiftUI examples/code, most of the complexity is hidden, but it's there, and you're going to have to interact with it to do anything non-trivial.
- Is SwiftUI the way?
SwiftUI has enabled me to build out huge amounts of beautiful UI quickly – faster than anything I've ever used. But you will run into things you can't do, forcing you have to fall back to AppKit/UIKit. And the area where AppKit/SwiftUI meet will disappoint and frustrate you. I just got done refactoring a huge amount of my app to use the "AppKit App Lifecycle" instead of the SwiftUI App lifecycle since I need some specific windowing behavior. Now I can't use .toolbar, .menu, and other stuff, which makes things much more complicated for me, and forces me to think about both SwiftUI/AppKit. Switching mental models like that, and trying to remember all the intricacies of both SwiftUI and AppKit is rough.
--------------
Regarding the performance issues of this specific post, my guess is they put everything into an ObservableObject, and used @Published properties to get bindings for their UI controls. This means any view with a reference to the ObservableObject gets re-rendered when @Published values change. Instead you need to silo your changes, so your entire App isn't redrawn every frame. This goes back to the complexity – it's not straightforward at all.
- jules 4y agoHow do you silo the changes? The issue was that changing a property of an object caused the inspector to be redrawn. With old fashioned UI libraries you would only change the value of one text field in the inspector. Can this be achieved with SwiftUI? To be honest I'm surprised that it's that slow even if the entire inspector is redrawn. Surely on a modern computer you can redraw a couple of text fields at 30fps?
- rudedogg 4y agoSee this answer: https://swiftui-lab.com/digital-lounges-2022/#data-15 https://swiftui-lab.com/digital-lounges-2022/#data-15 > Surely on a modern computer you can redraw a couple of text fields at 30fps? Yeah this is the tricky thing, with how (I'm guessing) the code looks, you would think it's only updating the text fields. But in reality it's probably re-rendering the entire hierarchy using the @EnvironmentObject. So the SceneKit view gets setup and rendered every update of the Slider. ------------------ I have real-time color pickers for changing all windows in my app. Same with font sizes. It's possible to make it work, you just have to modify your design (which is unfortunate).
- jules 4y agoAh I see, so each of the values that are shown in the inspector should become its own observable object? That sounds reasonable. > But in reality it's probably re-rendering the entire hierarchy using the @EnvironmentObject. So the SceneKit view gets setup and rendered every update of the Slider. I get that this is slower than only updating the single value, but what I don't understand is why even this is so slow? Browsers can render the right hand side of this inspector UI (https://chsxf.dev/assets/posts/5/map-editor-with-inspector.png https://chsxf.dev/assets/posts/5/map-editor-with-inspector.p...) at reasonable speed even if you rebuild the entire DOM for the fields in the inspector. I mean, it's one checkbox, one slider, and 7 text boxes and a bunch of labels. What is taking so much time here?
- saagarjha 4y ago> Surely on a modern computer you can redraw a couple of text fields at 30fps? No, this is actually the thing you should not be doing in SwiftUI. Ideally you text fields are not redrawing at 30 fps, actually, ideally nothing in your interface is doing this except when an animation is running and even then only the components that are animating. SwiftUI makes it really easy for you to accidentally start redrawing things that don't really need to be redraw far more often then you want, and that's how you get performance problems.
- pandatigox 4y agoOut of curiosity, what framework/library/solution are you using for your text editor? I've been researching this space for a while and syntax highlighting text editors are rare and sparse. There is this: https://github.com/krzyzanowskim/STTextView https://github.com/krzyzanowskim/STTextView for textkit2, but the author ended up writing his own text input client. How did you do about providing autocomplete, etc? Thanks!
- rudedogg 4y ago> Out of curiosity, what framework/library/solution are you using for your text editor? I'm still at the beginning of that part, but I'm doing it myself with TextKit 2 as well. > I've been researching this space for a while and syntax highlighting text editors are rare and sparse. I had the same experience as you when looking for information on how to go about it. I've come to the conclusion that no matter what an editor/IDE is going to be an ugly beast. This gave me some comfort in just forging ahead and trying to make good decisions as I go. And since I'm doing this all as a native app, I think I have a lot of wiggle room. As far as syntax highlighting, I just recently started calling into Zig (the language I'm building this for), and using the tokenizer to do basic syntax highlighting. I'll need to go a bit deeper into the compiler to do more advanced highlighting, but it's cool to have it working. > How did you do about providing autocomplete, etc? I'm not there yet, but these are the things I'm looking forward to working on. I'm currently working on sort of "core" things and trying to design them well. Things like the settings, window management, a command palette, etc. Getting them close to right early on seems important. I don't really do very technical posts, but I'm trying to blog a little about it: https://austinrude.com/tags/zig-ide/ https://austinrude.com/tags/zig-ide/. My biggest issue is second-guessing using Swift/SwiftUI and not trying to do it all myself with Zig, leading me to procrastinate. But I'm pretty far along, and think I'll probably release something eventually.
- darinf 4y agoYeah you end up designing models not to be logically separated but to instead isolate updates to Views. In theory those should align but they don’t always. And the method of finding objects thru the environment makes it all too easy to have big models that everything is listening too which of course really hurts perf. So easy to hold SwiftUI wrong.
- pixel_tracing 4y agoThis isn’t particularly the case changes to the render server are handed off before the runloop iteration ends, and before the runloop iteration ends all changes are aggregated (with the latest evaluated, i.e. @State, etc.) then we see the view invalidated once commits are handed off to the tender server. What you’d need to be careful off is ensuring your @State or @Published changes don’t too take too long to skip frames