Sounds like you haven't spent much time in React Native development yet. It's the poster child of the "just how many different modules can I take dependencies on so I don't have to write code?" school of thought. Also a Facebook/Meta gift to the world. So, much, overhead.
Thankfully I never got into React / React Native much. But a couple of my coworkers came into native iOS development from React Native, and it does show in things like how many and what kind of dependencies they add to projects (also in the way they structure the projects, typically with heavily reactive and massive architectures, but that's for another day). I'm usually the opposite: I try to roll in-house solutions unless there's clear benefit in using a pre-existing library. I'm particularly averse of libraries from small developers. Not because they're bad (they aren't) but because the documentation is usually lacking and it's much harder to find people with the same issues in Google (purely because the user base is orders of magnitude smaller).
I had a problem with this last week, with a little library called
XCoordinator. The idea behind the library is not a bad one, but the API names are so similar to Apple's own navigation APIs that finding any info on Google about minimal issues is incredibly difficult. And, because it's a less known library, there's a much slimmer chance that anyone new to the project knows how this library works.
A couple months before I had to remove a image caching library too from another project, because the image views the framework provided didn't animate correctly in SwiftUI, and there was nothing we could do about it. This was even worse, because matching the caching feature set the app was using required a grand total of 3 classes and less than two days of work, so the restrictions the 3rd party library was imposing on us were totally avoidable. I know there's another library in the project to access elements in the keychain (apparently, because Apple's API is 'too verbose'), which saves like 30 lines total vs Apple's API, and is going to be more confusing to everyone who gets into the project because it's almost guaranteed that the new people we get in haven't used this library.
So one thing on SwiftUI that I've found little to no resources on, but am curious about is understanding how Apple builds components that are designed to be re-used across different platforms. Button for example, which behave differently depending on Style and the like applied to it, and different platforms set a default style as well as allowing different styles depending on the platform. While you can find out how to do various things in SwiftUI, nobody seems to bring it together into how to build good reusable components at the same quality level of what Apple provides.
As best as I can figure, Button owns the content/state, but then delegates the final rendering to the active style that conforms to ButtonStyle. This is just an environment value at the end of the day, I think. Since environment settings have defaults, there's that as well. So it's probably more straight-forward than I fear. Any ButtonStyle can even just provide an NSViewRepresentable in the case of wanting the standard Mac button style rather than a custom button.
Since my app uses a custom ProgressView with drag/click functionality, and I've now got 3-4 different styles I want to implement, this seems like a pretty good control to learn this strategy on.
I hadn't though about it, but I'll keep this in mind when creating new UI components. I try to match Apple's APIs design wherever possible, but I hadn't ever done anything like
.buttonStyle
or
.listStyle
for custom components. The way I usually see it done is either by creating different, separate components (
FooPrimaryButton
,
FooSecondaryButton
...), which obviously hurts reusability (and often makes the UI and behavior diverge over time for components that should behave essentially the same), or by enforcing extra style arguments at initialization (
FooButton(color: .primary)
). But for a component with many different styles those kind of modifiers are probably best, as you minimize the amount of code duplication in both the view implementation and the call site.
For different iOS/macOS implementations, I don't know what's common in the industry, as I've only worked on iOS or iPadOS apps. For my own apps, I maintain separate implementations (when necessary) for the same custom SwiftUI component in iOS/macOS by using
#if targetEnvironment
in the implementation of the component, keeping a single view type externally. So I can do things like
CustomComponent()
throughout the app that translate to different views on different environments.