SwiftUI
MVVM: Model - View - ViewModel
ContentModel.swift
import Foundation
struct ContentModel {
var content: String
mutating func performIntent() {
content = "Hello " + content
}
}
ContentViewModel.swift
import SwiftUI
class ContentViewModel: ObservableObject {
@Published private(set) var contentModel: ContentModel
init(content: String) {
contentModel = ContentModel(content: content)
}
// MARK: Intent(s)
func performIntent() {
contentModel.performIntent()
}
}
ContentView.swift
import SwiftUI
struct ContentView: View {
@ObservedObject var contentViewModel: ContentViewModel
var body: some View {
Text(contentViewModel.contentModel.content)
.onTapGesture {
contentViewModel.performIntent()
}
.frame(width: 100, height: 100)
}
}
Views and Modifiers
- Views
- Image Assets
- Color Assets
- Modifiers
Common Views
Text("Hello SwiftUI")
.font(.subheadline)
.foregroundColor(.secondary)
Text("Fancy")
.font(.system(size: 20, weight: .bold, design: .rounded))
Image(update.image)
.resizable()
.aspectRatio(contentMode: .fit)
View Combiners
HStack {
}
VStack {
}
ZStack {
RoundedRectangle(cornerRadius: 10)
Text("🍏")
}
ForEach(image) { image in
Image(image)
.resizable()
.frame(height: 100)
}
Modifiers
Full width text
Text("")
.frame(maxWidth: .infinity, alignment: .leading)
Modal View
Button(action: { self.sheetPresented.toggle() }) {
Text("Button")
}
.sheet(isPresented: $sheetPresented) {
ContentView()
}
Data flow primitives / Properties
@State var showUpdate = false
@Binding var showProfile: Bool
@Published var updates: [Update] = updateData
@ObservedObject var store = UpdateStore()
Binding properties denoted by $
-prefix, e.g.
ViewWithBinding(bindingVariable: $variable)
Combine
Store Class
import SwiftUI
import Combine
class UpdateStore: ObservableObject {
@Published var updates: [Update] = updateData
}
@ObservedObject var store = UpdateStore()
// store.updates
Binding state variables in a subview
struct Home: View {
@State var state: Bool
var body: some View {
// …
ExtractedView(subviewState: $state)
// …
}
}
struct ExtractedView: View {
@Binding var subviewState: Bool
// …
}
@State
struct ContentView: View {
@State var dragOffset: CGSize
// ...
}
Observable Object
class ViewModel: ObservableObject {
@Published private var model
}
struct ContentView: View {
@ObservedObject var viewModel: ViewModel
// ...
}
Geometry
Positioning
.offset
Modifier (aka relative position).position
Modifier (aka absolute position)- Alignment
.leading
.trailing
.trailing
SwiftUI Coordinate Spaces
.global
.local
.named("XYZ")
Modifier:
View().coordinateSpace("XYZ")
Detect Screen Size
let screen = UIScreen.main.bounds
screen.height
screen.width
GeometryReader
GeometryReader { geometry in
// geometry.frame(in: .global).minX
// geometry.size
}