Skip to content

Instantly share code, notes, and snippets.

struct CountView: UIViewControllerRepresentable {
@EnvironmentObject var counter: ObservableCounter
typealias UIViewControllerType = CountViewController
func makeUIViewController(context: Context) -> CountViewController {
return CountViewController()
}
class CountViewController: UIViewController {
private let countLabel = UILabel()
var count = 0 {
didSet {
countLabel.text = "Current count: \(count)"
}
}
struct ContentView: View {
@EnvironmentObject var counter: ObservableCounter
var body: some View {
VStack {
Text("Current count: \(counter.count)")
Button("Increment", action: { counter.increment() })
}
.padding()
class ObservableCounter: ObservableObject {
@Published var count = 0
func increment() {
count += 1
}
}
@main
struct MyApp: App {
struct RestaurantDetailView: View {
let viewModel: RestaurantDetailViewModel
var body: some View {
ObservingView(publisher: asPublisher(viewModel.output)) { output in
VStack {
Text(output.name)
Text(output.priceCategory)
// etc
class RestaurantDetailViewModelImpl(api: Api, restaurantId: Int): RestaurantDetailViewModel {
private val _restaurant = api.restaurant(restaurantId)
private val _reservations = api.restaurantReservations(restaurantId)
private val _output = combine(_restaurant, _reservations) { restaurantResponse, reservationsResponse ->
// for simplicity we ignore error handling and exclude specific loading state for when the restaurant is loading
RestaurantDetailViewModel.Output(
name = (restaurantResponse as? Response.Success)?.data?.name ?: "Loading or error...",
priceCategory = (restaurantResponse as? Response.Success)?.data?.priceCategory ?: "Loading or error...",
interface RestaurantDetailViewModel {
val output: CFlow<Output>
data class Output(
val name: String,
val priceCategory: String,
val reservations: Reservations
) {
sealed class Reservations {
object Loading: Reservations()
struct RestaurantDetailView_Previews: PreviewProvider {
static var previews: some View {
InnerView(
output: RestaurantDetailViewModelOutput(
name: "My restaurant",
priceCategory: "Expensive",
reservations: RestaurantDetailViewModelOutput.ReservationsLoading()
)
)
}
struct RestaurantDetailView: View {
let viewModel: RestaurantDetailViewModel
var body: some View {
ObservingView(publisher: asPublisher(viewModel.output), content: InnerView.init)
}
}
private struct InnerView: View {
import Combine
import SwiftUI
import shared
class ObservableRestaurantDetailViewModel: ObservableObject {
@Published var viewModelOutput: RestaurantDetailViewModelOutput?
init(viewModel: RestaurantDetailViewModel) {
asPublisher(viewModel.output)