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.
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.
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.