Stanford CS193p 2023
Lecture 1 Getting Started with SwiftUI
- You can put all assets like video, sound, icons, images in
assets folder
- Path Bar shows exact path where our cursor is right now
- Structs are really important in SwiftUI pretty much everything
is struct.
- struct in SwiftUI conforms to View. It means this structure
called ContentView behaves like a View. Here behaves can be
also considered behaviour so focus is on functionality not on
data. So it is functional programming just for clarity OOP is
more about data encapsulation both the other hand functional
programming is behaviour encapsulation.
- VStack contains list of different views which in postprocessing
returns a TupleView of those elements.
- Thing which converts VStack elements List into TupleView is
called ViewBuilder
- Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint) Methods like
`.imageScale(.large)` and `.foregroundStyle(.tint)` Are called
viewModifiers.
- If you apply any modifier to VStack, Stack it will be applied to
all subviews inside them.
Note that some of the view modifiers are not applicable to
some views and these views can ignore them like
applying .imageScale to Text then Text will ignore it.
- Do not write swiftUI code longer than 20 lines preferably only
12 lines max
Lecture 2 More SwiftUI
- We can do variable assignments while creating views but not
further modifications to those variables
For e.g
ZStack {
var base: RoundedRectangle =
RoundedRectangle(cornerRadius: 12) // Allowed
var x: Int = 1 // Allowed
x = x + 1 // NOT Allowed
}
- Even though var is allowed mostly we will use let as these
views are read only anyways
- If you want to modify variable like isFaceUp you can use
@State this internally creates a pointer so now view stays
immutable as memory is same but at the same time you can
change value at that memory location.
Lecture 3 MVVM
- Views should be stateless and should just reflect whatever
happens to model. So marking @State etc should be rare.
- View is declared it means we are not implementing it in
imperative manner but just declaring.
- View is reactive so any change in model data updates ui
Lecture 4 Applying MVVM
- 0:32:30 We don’t know order in which properties will be
initialised we cannot assume that they will be in order present
in source code
- 1:07:00 @ObservableObject shouldn’t have default value
instead caller should pass value
Lecture 5 Protocols, enum, Optional
- 0:11:30 If all properties of Struct are Equatable swift
automatically synthesises Equatable conformance to Structure
without adding explicit conformance method
- 0:29:48 If you add // FIXME: In comment it will show bandaid
in function list in top bar
Lecture 6 Layout, @ViewBuilder
- 0:36:34 SwiftUI draws on pixel boundaries. All the work we do
is in points when we pass any numbers those are point values
and each point can have 1, 2 or 3 pixel depending on device
screen so for higher pixel screen ui will look more smooth.
- 0:44:05 If we add @ViewBuilder to custom view we don’t need
to return result it makes code more readable
Lecture 7 Shape, ViewModifier, Constants
0:18:19 stroke and fill modifiers are shape modifiers not view
modifiers
0:40:30 ViewModifiers are only way beside shapes to do custom
animation
Lecture 8 Animation (Part 1)
0:04:01 Property observers like willSet, didSet are more useful
in model rather than view. For views use .onChange(of:) {}
ViewModifier.
Lecture 9 Animation (Part 2)
0:30:00 Use TimeLineView to do time. Based animations.
0:48:40 Think very carefully before using frame and exact sizes
it might be really unnecessary and there might be better ways.
0:54:50 if we don’t want to add any transition effect even the
default opacity transition has to be removed then
use .transition(.identity)
0:56:00 But .transition(.identity) remove any
matchedTransitionGeometry effect as well so if we want to
keep other effects we should use
`.transition(.asymmetric(insertion: .identity, removal:
identity))`
Lecture 10 Emoji Art
0:22:30 emojis.uniqued.map { String($0)} is same as
emojis.uniqued.map(String.init)
0:36:06 If we want to add anything ui related to model we can
do it by adding an extension in view for that model element.
0:44:27 when of passing initialised object as parameter you can
say only .init() type inference will take care of the rest for e.g.
instead of calling EmojiArt.Emoji.Position(x: , y:) you can
call .init(x: , y:).
0:50:00 To support drag and drop we need to conform to
Transferable
0:51:27 A view can be drag initiator by
applying .draggable(Transferable) modifier.
0:51:43 A view can be dropped upon if they have
dropDestination modifier.
0:53:00 isTargeted closure tells view. They haven’t dropped it
yet, they’re dragging over you, so do you want to highlight
yourself but its optional and generally not needed.
1:01:45 If you want to support multiple types to be draggable
you can create separate enum which will conform to
Transferable
Lecture 11 Gestures, 2nd MVVM
0:07:27 You can only update gesture state only while it’s
happening. When it over it returns to its initial value.
0:08:23 .updating will cause the closure you pass to be called
when fingers move.
0:29:40 when you are applying multiple gestures like drag as
well as zoom to view be careful of sequence as some gestures
may consume the gestures and subsequent gestures won’t
receive anything.
0:30:07 Instead of that do it
like .gesture(panGesture.simultaneously(with: zoomGesture))
Lecture 12 Persistence, Property Wrappers
1:00:56 Property wrappers- are denoted using @ like
@Something. Internally it’s actually a struct. These structs
encapsulate some “template” behavior applied to the vars they
wrap.
1:01:27 Examples of property wrappers
Making a var live in the heap (and update its view)
(@State)
Make a var publish its changes (@Published)
Causing a view to redraw when a published change is
detected (@ObservedObject)
The property wrapper creates a syntactic sugar to make
these structs easy to create/use
1:02:50 So when we define property wrapper as
@Published var emojiArt: EmojiArt = EmojiArt()
is really just a struct as below:
struct Published {
var wrappedValue: EmojiArt
var projectedValue: Publisher<EmojiArt, Never>
}
Also there are some property wrappers like @Namespace
where we don’t provide any data type. But such property
wrappers have internally provided data types.
1:03:30 When we create property wrapper swift provides some
vars to us:
for above case a var is created and made available as
follows:
var _emojiArt: Published = Published(wrappedValue:
EmojiArt())
1:04:16 Also the variable emojiArt is also internally computed
as follows:
var emojiArt: EmojiArt {
get { _emojiArt.wrappedValue }
set { _emojiArt.wrappedValue = newValue }
}
1:05:46 projectedValue can be accessed using $ sign e.g.
$emojiArt. Its a publisher
Lecture 13 Presenting Views, Navigation
Lecture 15 Document Architecture
0:28:40 Using Notifications for events like db changes, system
changes etc is old way. Modern approach is to use
@Environment to get a value out of EnvironmentValues.
0:37:05 Use @ScaledMetric to update system fixed fonts
dynamically when user changes font sizes with accessibility