Skip to content

Instantly share code, notes, and snippets.

@sergiocampama
Created December 10, 2024 12:30
Show Gist options
  • Save sergiocampama/b9e74be9e5fbe5e78de32bef2f5e6fd3 to your computer and use it in GitHub Desktop.
Save sergiocampama/b9e74be9e5fbe5e78de32bef2f5e6fd3 to your computer and use it in GitHub Desktop.
ViewModelAPI with Views
import UIKit
class View: UIView {
init() {
super.init(frame: .zero)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
protocol ViewModelAPI {
associatedtype ViewType: View
var view: ViewType! { get }
func sizeThatFits(_ size: CGSize) -> CGSize
}
class ViewModel<V: View>: ViewModelAPI {
var view: V!
func sizeThatFits(_ size: CGSize) -> CGSize {
return .zero
}
}
protocol RootViewModelAPI: ViewModelAPI {
var title: String { get }
}
final class RootViewModel: ViewModel<RootView>, RootViewModelAPI {
let title: String
init(title: String) {
self.title = title
super.init()
view = ViewType(viewModel: self)
}
}
final class RootView: View {
var viewModel: any RootViewModelAPI
init(viewModel: any RootViewModelAPI) {
self.viewModel = viewModel
super.init()
}
override func layoutSubviews() {
super.layoutSubviews()
print(viewModel.title)
}
}
final class VMViewController<VM: ViewModelAPI>: UIViewController {
private let viewModel: VM
init(viewModel: VM) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(viewModel.view)
}
}
enum Controller {
func start() {
let viewController = VMViewController(viewModel: RootViewModel(title: "Hello, world!"))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment