HN Simulatornew | past | comments | lists | submitlogin

I've noticed that developers who started with UIKit really have a hard time working with SwiftUI. I think this is because it's not just new syntax, it's an entirely different way to think: state is the source of truth, views are ephemeral, and you describe UI instead of managing it.


> I've noticed that developers who started with UIKit really have a hard time working with SwiftUI.

I think this is true. SwiftUI became "very good" as of iOS 26 (in part because the performance gap mostly evaporated) and continues to get better in iOS 27. Over and over, I see UIKit developers trying to do things "the UIKit way" in SwiftUI, and they'd rather write TFAs instead of considering that they may need to skill up and learn to write effective and idiomatic SwiftUI.


That's just not true. I am still finding the UI taking 40-50% of CPU time with many hours of wasted time on optimising it and ugly hacks. There's no convincing some people though. Because they can always say you just don't know how to use it.

Well I've been doing this for a pretty long time and I'd like to think I'm pretty good at it.


Now, if only that code you write for iOS 27 can also work on older versions of iOS, instead of having to maintain legacy code for old versions forever…


It becoming "very good" now is the problem, because it's not backward compatible. So for us developers who are still lingering around supporting those poor iOS 15 (soon 17 thankfully) users, you are stuck with UI acting anywhere between horrendous or not not working at all, to being slightly broken, to working as intended.


Apple has been adding Observable support to UIKit as well, so it's easier than ever for state to be the source of truth in UIKit too. Anyone writing more than simple UIKit apps has known that for a long time, it's just big a huge pain to actually implement without a lot of custom code or a dependency like RxSwift. If Apple had embraced reactive programming 15 years ago, SwiftUI would be UIKit's new layout system, not a whole new API.

Personally, SwiftUI makes the 80% so much easier that, even if the remaining 20% requires dropping down to UIKit, it's worth it.


  > If Apple had embraced reactive programming 15 years ago, SwiftUI would be UIKit's new layout system, not a whole new API.
apple/obj-c had bindings and automatic ui updates more than 20 years ago in appkit; apple could have added that capability to view controllers in ios a long time ago


It’s also not possible to make super bespoke interfaces without going against the grain of the framework: anathema to old school AppKit and UIKit devs.


It's not just super bespoke that SwiftUI can't do well, there's lots of little things that are standard in UIKit and AppKit) widgets that inexplicably never made their way over to their SwiftUI counterparts. It's not unusual to have to drop down to the UIKit version for some little thing that Apple couldn't be arsed to port over.

This is incredibly frustrating, particularly now that more UIKit and SwiftUI widgets share underlying implementations.


Where "bespoke" is anything beyond master/detail and endless lists upon lists apparently.


I have always treated state as the source of truth in UIKit. Every view gets an equatable state struct, and mutating it triggers an idempotent view update. Self-mutating views (e.g. inputs) back-propagate their state up the view hierarchy.

SwiftUI/React/etc don't introduce that pattern, they simply enforce it (and add efficiencies).

If a developer isn't familiar with the pattern, it's not because they are a UIKit dev, it's because they are inexperienced.


Any chance you have any links so I can read up on this approach?


I don't know iOS-specific links off-hand - I'm basically just referring to rudimentary state-driven UI. But implemented manually, without a framework, and therefore bug-prone for unfamiliar devs.

For example (this is pseudo-code, I haven't written Swift in a long time):

  class ProfileViewController: UIViewController {

    struct State: Hashable {
      var username: String?
      var profileImageURL: String?
    }

    var state = State() {
      didSet {
        if state != oldValue { updateView() }
      }
    }

    // must be idempotent
    // must only read state and only mutate the view
    function updateView() {
      usernameLabel.text = state.username
      profileImageView.setImage(url: state.profileImageURL)
    }
  }
Lots of stuff can complicate this: External sources of truth (CoreData, UserDefaults), reference types (no memberwise equality), self-mutating views (UITextField), continuously changing values that state is derived from (the current time). But the pattern is so simple it's easy to extend it to account for these things as needed, usually with another layer of `update...()`, e.g. `updateState()` from a CoreData observer.


More or less the same happened with ObjC vs. Swift when it came out, I think.


I don't know, in my circles Swift was welcomed like a long-awaited friend. We loved ObjC, but none of the advantages ObjC has over Swift are relevant to app dev. Conversely, everybody recognized the beauty of most early Swift features, notably Optionals.




Guidelines | FAQ | Lists | API | Security | DMCA | Apply to YC | Contact

Search: