- ViewModel is never calling View but View calls ViewModel
- One ViewModel can be used by many Views and that is why it's a class
- Holding
optionand clicking a variable name allows to do all kind of things like rename. -
mutatingkeyword is used front offuncwhen it's changingself - in
struct EmojiMemoryGameView: View {Viewis called protocol (constrains and gains). The idea is that we gain something (functions) from using it but it also contrains us to do something like havevar body: some View
Reactive
-
ObservableObjectis constraint and gain that gives a class (ViewModel) ability to follow changes. Every time something changes it updates the UI.-
objectWillChange.send()is can be added to functions where some object will change. - It's more common to add
@Publishedproperty wrapper front of the variables that will change because that way you don't forget to addobjectWillChange.send()to some position.- Behind the scenes it checks that every time that variable is changes it calls
objectWillChange.send()
- Behind the scenes it checks that every time that variable is changes it calls
-
-
@ObservedObjectis added front of ModelView in View class to redraw it every time the ModelView changes. -
protocolis like stuct/class that can contain vars and functions but it doesn't had implementation to them.- Classes and structs can use
protocolfollowing wayclass Car: VehicleIt's possible to implement multiple protocols by separating them with commas. - Protocols can also inherit other protocols
protocol Vehicle: Moveable ... - protocol offers constrains and gains
- The idea in protocols is that multiple structs/classes can use it and then if it's extended all of them get the new feature
- Classes and structs can use
-
extensionis used to add new functionalities to structs, classes, protocols - Protocols are useful because they say what the types (structs/classes/other protocols) are capable of and also demand certain behavior.
protocol Greatness {
func isGreaterThan(other: Self) -> Bool
}
extension Array where Element: Greatness {
var greatest: Element {
// for-loop through all the elements
// which (inside this extension) we know each implementes the Greatness protocol
// and figure out which one is greatest by calling isGreaterThan(other:) on them
return the greatest by calling isGreaterThan on each Element
}
}
-
Selfmeans that type comes from the thing that is implementing that protocol.
Layout (49:57)
- HStack and VStack
- Offers space to its "least flexible" subviews first
- Image: "inflexible"
- Text: "slightly more flexible"
- RoudedRectangle: "flexible"
- Defaults work a little bit differently in different devices and that is why we should keep them and not put specific numbers because those probably doesn't work as many device
-
Spacertakes the space given and draws nothing -
DividerDraws line (horizontal or vertical depending the stack)
- Offers space to its "least flexible" subviews first
HStack {
Text("Important").layoutPriority(100)
Image(systemName: "arrow.up") // default layout priority is 0
Text("Unimportant")
}
- Important text takes the space it wants
- Then image takes the space it wants
- Finally Unimportant text takes the remaining space
Demo (1:12:04)
struct CardView: View {
GeometryReader { geometry in
ZStack {
if self.card.isFaceUp {
RoundedRectangle(cornerRadius: 10.0).fill(Color.white)
RoundedRectangle(cornerRadius: 10.0).stroke(lineWidth: 3)
} else {
RoundedRectangle(cornerRadius: 10.0).fill()
}
}
.font(Font.system(size: min(geometry.size.width, geometry.size.height) * 0.75))
}
It's common to move the numbers to a "control panel". In one place it's easy to modify them and the main code becomes cleaner.
Top comments (0)