Really the problem is so much logic is being done inline with the view hierarchy. Like the close button action, it’s a big chunk of code and means I couldn’t even tell it was the close button until I scrolled further down. Actions like that probably should have been pulled off into their own functions.
It could also use actual comments, and perhaps breaking more things putout into subviews.
I agree that ideally the code could be organized a lot better, but think about it like this:
It is the fully working safari UI in only 1000 lines of code. Additionally the declarative approach of SwiftUI together with the type system makes it certainly correct in many ways: no rendering bugs, no invalid states, probably no memory leaks, no cyclic dependencies creeping in.
Try to build this in Java Swing, UIKit, Html/Css/Js or any other UI library.
Flutter might come close, react/vue/svelte as well, if you assume sensible predefined components. But they work similar to SwiftUI and the resulting one-file might look pretty similar.
Agreed, i hacked together something resembling a midi-sequencer UI in about 1000loc with JS+Vue.
I have an old editor written in Java/Swing that takes more and more willpower to work on every time because handling state update bugs is what i spend half my time on.
Probably could have made most of the event handlers separate methods rather than lambdas. That would have made the UI structure easier to read. I don’t know Swift or SwiftUI though.
Yeah you would never want to write Swift code professionally like this (at least where I work we don’t). I believe the developer of this said this was intentional (each file encapsulates an entire “app”).
A lot of this would be broken out into it’s own file (e.g. extensions on basic types like Arrays would go in Array+Extensions.swift).
Each view would go in its own file.
You would break out code into separate functions instead of inlining it inside closures in the view body.
SwiftUI (though not usually Swift in general) does have a problem with over-indentation IMO. You barely have to go more than 3 levels deep in the view hierarchy you are producing before your code feels like more white space than code.
It’s fairly poorly abstracted, I guess OP is writing this more for fun. You could hide a lot of this implementation stuff in extensions, view modifiers and by composing views and splitting out event handlers. It isn’t representative of SwiftUI really.
Very cool project but definitely not best practice. You could reduce the number of State variables using one or more shared state objects and access via environment at certain points in the view hierarchy.
Generally it’s better to compose views, by that I mean you often have to because of the compiler. I’m surprised this file even compiles! The Swift compiler usually chokes on much smaller views.
> You could reduce the number of State variables using one or more shared state objects and access via environment at certain points in the view hierarchy.
Just a personal opinion here, but those shared state objects and SwiftUI + glorified singletons really hurts every time I see it. It's so prevalent in online tutorials like Ray Wenderlich and the such.
Honestly, it's hard to avoid and can be done but requires a significant effort. I was hoping for Apple to come up with a more elegant solution during WWDC 21 but so far I haven't seen anything to improve this situation.
I really think SwiftUI is hamstrung by trying to create a DSL that can describe a UI spanning everything from your watch to a desktop. The Apple world is starting to feel more like Google and MS with multiple UI frameworks coming out of different groups and no clear communication on what the long term plan is or expectation from developers. From what I can see though it looks like Catalyst is still very much a thing and I don't think that UIKit is going away anytime soon.
Did you look at the file? Yes, comparatively using a non-declarative approach would render much simpler code. Perhaps the author is not writing SwiftUI proficiently? Having used SwiftUI myself I would argue that this is not the case.
It reminds me of why I am not a big fan of Flutter either. Not a fan of the deep nesting which both SwiftUI and Flutter needs to do for even moderately complex UIs.
This is a fun project so whatever code goes, but this could easily be broken into many small chunks. There’s even a context my button to pull subsections out into smaller strict automatically.
Deep nesting suggests that you need to break parts out into their own views (or pull logic out into their own functions). Like the close box in that file, it’s a great candidate for turning into its own view, or at least moving it’s action into a separate function.
This! It’s generally a good idea to have a lot of smaller “dumb” views that are stateless and depend on their parameters, and a few “intelligent” views that bring the children together and provide state logic. That puts reasonable boundaries between the view and business logic, even in declarative code like SwiftUI.
I’m not a Swift or SwiftUI expert, but have written declarative UI quite a bit. Don’t imagine some base best practices would differ too much.
It could also use actual comments, and perhaps breaking more things putout into subviews.