WEBVTT

1
00:00:00.080 --> 00:00:03.080
<v Speaker 1>Welcome back to the deep dive. Today, we're really jumping in,

2
00:00:03.560 --> 00:00:08.560
<v Speaker 1>launching straight into the well, the bedrock of the Apple ecosystem.

3
00:00:08.640 --> 00:00:12.160
<v Speaker 1>Our goal isn't just to skim the surface. We want

4
00:00:12.160 --> 00:00:15.880
<v Speaker 1>to pull out those foundational pillars, the architecture, the tools,

5
00:00:16.280 --> 00:00:18.120
<v Speaker 1>and really the philosophy behind Swift.

6
00:00:18.239 --> 00:00:19.920
<v Speaker 2>Yeah, the core ideas exactly the.

7
00:00:19.879 --> 00:00:23.160
<v Speaker 1>Stuff any aspiring iOS dev needs to get. This is

8
00:00:23.199 --> 00:00:26.399
<v Speaker 1>about understanding the why behind the code.

9
00:00:26.160 --> 00:00:29.440
<v Speaker 2>You write, right, And I think for anyone starting out,

10
00:00:29.480 --> 00:00:33.039
<v Speaker 2>the key takeaway is that Swift isn't just another language

11
00:00:33.039 --> 00:00:36.359
<v Speaker 2>thrown out there. It was built very deliberately with specific goals.

12
00:00:36.399 --> 00:00:41.600
<v Speaker 2>Specific goals safety, clarity, and performance that shapes everything, how

13
00:00:41.640 --> 00:00:44.039
<v Speaker 2>you declare variable, how memory works, all of it.

14
00:00:44.240 --> 00:00:47.000
<v Speaker 1>Okay, so let's unpack that starting big picture. Yeah, an

15
00:00:47.039 --> 00:00:49.679
<v Speaker 1>iOS app. Yeah, it's like its own little world, right,

16
00:00:49.719 --> 00:00:50.439
<v Speaker 1>what's at its core?

17
00:00:50.679 --> 00:00:52.960
<v Speaker 2>Fundamentally, you can think of any app as having let's

18
00:00:52.960 --> 00:00:57.079
<v Speaker 2>say three main parts the screen what the user interacts with, Okay,

19
00:00:57.119 --> 00:00:59.640
<v Speaker 2>the code, the logic, the instructions, and the data the

20
00:00:59.640 --> 00:01:04.280
<v Speaker 2>information it holds onto screen code data simple enough, and

21
00:01:04.319 --> 00:01:06.959
<v Speaker 2>the whole thing operates in what we call an event

22
00:01:07.159 --> 00:01:08.159
<v Speaker 2>driven paradigm.

23
00:01:08.239 --> 00:01:11.239
<v Speaker 1>Right, Event driven. That's important. It's not just running top

24
00:01:11.280 --> 00:01:12.879
<v Speaker 1>to bottom like a script, not at all.

25
00:01:13.000 --> 00:01:15.879
<v Speaker 2>The phone or iPad is basically just sitting there waiting,

26
00:01:16.359 --> 00:01:19.000
<v Speaker 2>waiting for an event like a button tap, a button tap,

27
00:01:19.079 --> 00:01:23.439
<v Speaker 2>a notification, maybe a timer firing. Something happens. The operating

28
00:01:23.480 --> 00:01:27.200
<v Speaker 2>system catches that event, figures out which bit of your

29
00:01:27.200 --> 00:01:29.519
<v Speaker 2>code needs to handle it, and runs that.

30
00:01:29.480 --> 00:01:32.280
<v Speaker 1>Code, and that code changes something always.

31
00:01:32.760 --> 00:01:36.719
<v Speaker 2>It leads to a change in state, maybe updating what's

32
00:01:36.760 --> 00:01:40.159
<v Speaker 2>on the screen, maybe changing the stored data. This constant

33
00:01:40.280 --> 00:01:44.640
<v Speaker 2>loop weight respond update. That's the pulse of an iOS app.

34
00:01:44.799 --> 00:01:48.159
<v Speaker 1>Got it, and the place we orchestrate all this code

35
00:01:48.439 --> 00:01:52.159
<v Speaker 1>UI configuration, that's xcode. Can you walk us through the

36
00:01:52.239 --> 00:01:54.239
<v Speaker 1>essential parts of that environment. It can look a bit

37
00:01:54.280 --> 00:01:55.200
<v Speaker 1>intimidating at first.

38
00:01:55.280 --> 00:01:57.920
<v Speaker 2>Sure xcode is your main hub, your ide. Think of

39
00:01:57.959 --> 00:02:00.319
<v Speaker 2>it in like four main zones you'll use constantly. On

40
00:02:00.359 --> 00:02:03.400
<v Speaker 2>the left, the navigation pain. That's for finding things, your files,

41
00:02:03.439 --> 00:02:05.079
<v Speaker 2>your classes, images.

42
00:02:04.640 --> 00:02:06.840
<v Speaker 1>All that, your project structure exactly.

43
00:02:07.239 --> 00:02:09.199
<v Speaker 2>Then the big area in the middle that's the editor

44
00:02:09.240 --> 00:02:12.280
<v Speaker 2>pain where you actually write the code. Sense Down at

45
00:02:12.280 --> 00:02:15.080
<v Speaker 2>the bottom, you've got the debug pain super important. That's

46
00:02:15.120 --> 00:02:18.120
<v Speaker 2>where you see print messages, check variable values. When the

47
00:02:18.120 --> 00:02:19.360
<v Speaker 2>app is running, find.

48
00:02:19.120 --> 00:02:21.120
<v Speaker 1>Crashes, your troubleshooting area yep.

49
00:02:21.639 --> 00:02:24.199
<v Speaker 2>And then on the right the inspector pain. This one's

50
00:02:24.240 --> 00:02:27.360
<v Speaker 2>context sensitive. If you're looking at code, it might show documentation.

51
00:02:27.879 --> 00:02:30.280
<v Speaker 2>If you're designing UI, it shows all the settings and

52
00:02:30.319 --> 00:02:32.759
<v Speaker 2>attributes for buttons, labels, whatever.

53
00:02:33.199 --> 00:02:37.680
<v Speaker 1>So navigator, editor, debug, inspector get comfortable with those four.

54
00:02:37.800 --> 00:02:39.439
<v Speaker 2>That's pretty much your core workflow.

55
00:02:39.520 --> 00:02:42.840
<v Speaker 1>Yeah, okay, one quick but crucial thing before we dive

56
00:02:42.879 --> 00:02:46.800
<v Speaker 1>into Swift itself. The bundle identifier. What is that exactly?

57
00:02:46.919 --> 00:02:50.360
<v Speaker 2>Ah? Yeah, the bundle ID. It's basically the app's unique

58
00:02:50.439 --> 00:02:53.120
<v Speaker 2>social security number. You could say, okay, it has to

59
00:02:53.159 --> 00:02:56.360
<v Speaker 2>be globally unique. It's how the app store and the

60
00:02:56.360 --> 00:02:59.879
<v Speaker 2>device itself identifies your specific app from all the millions

61
00:02:59.879 --> 00:03:00.639
<v Speaker 2>of others.

62
00:03:00.560 --> 00:03:01.800
<v Speaker 1>Like a web address for an app.

63
00:03:02.080 --> 00:03:04.599
<v Speaker 2>That's a great analogy, and it usually follows that reverse

64
00:03:04.680 --> 00:03:07.599
<v Speaker 2>domain name style like calm dot your company dot your

65
00:03:07.639 --> 00:03:10.199
<v Speaker 2>rap name. Super important to get right right.

66
00:03:10.639 --> 00:03:14.000
<v Speaker 1>Okay, Now into Swift itself. This is where as you said,

67
00:03:14.000 --> 00:03:17.599
<v Speaker 1>the philosophy really shows this focus on safety and clarity,

68
00:03:18.280 --> 00:03:23.240
<v Speaker 1>sometimes even prioritized over maybe raw speed in some micro benchmark.

69
00:03:23.599 --> 00:03:25.960
<v Speaker 1>How does that show up right away? Just in declaring

70
00:03:26.159 --> 00:03:27.080
<v Speaker 1>basic values.

71
00:03:27.360 --> 00:03:32.360
<v Speaker 2>It shows up immediately with let versus var immutability, constants

72
00:03:32.400 --> 00:03:36.120
<v Speaker 2>and variables right VARs for variables values that can change later.

73
00:03:36.319 --> 00:03:38.639
<v Speaker 2>Let is for constant values you set once and they

74
00:03:38.680 --> 00:03:39.560
<v Speaker 2>never change after that.

75
00:03:39.599 --> 00:03:41.360
<v Speaker 1>And the swift way is the swift way.

76
00:03:41.400 --> 00:03:45.080
<v Speaker 2>The strong recommendation is always use let unless you absolutely

77
00:03:45.120 --> 00:03:48.520
<v Speaker 2>know you need to change the value later, default to immutability.

78
00:03:48.599 --> 00:03:51.000
<v Speaker 1>Why is such a strong push for let, I mean,

79
00:03:51.039 --> 00:03:54.680
<v Speaker 1>besides just preventing accidental changes, are there technical benefits?

80
00:03:54.759 --> 00:03:58.400
<v Speaker 2>Oh? Definitely. Predictability is huge obviously, but also performance. When

81
00:03:58.400 --> 00:04:01.159
<v Speaker 2>the Swift compiler sees let, it knows that piece of

82
00:04:01.199 --> 00:04:02.159
<v Speaker 2>memory is fixed.

83
00:04:02.360 --> 00:04:04.240
<v Speaker 1>Ah, so it can optimize.

84
00:04:04.039 --> 00:04:07.439
<v Speaker 2>Exactly, It can store it more efficiently, maybe inline, It

85
00:04:07.479 --> 00:04:10.360
<v Speaker 2>skip checks it might need for a variable. And for

86
00:04:10.439 --> 00:04:13.000
<v Speaker 2>other developers reading your code, let me as a clear

87
00:04:13.039 --> 00:04:16.920
<v Speaker 2>signal this value is stable. Don't worry about it changing unexpectedly.

88
00:04:17.399 --> 00:04:18.600
<v Speaker 2>It's safer coding.

89
00:04:18.879 --> 00:04:22.279
<v Speaker 1>Fundamentally, That safety focus carries right over to types, doesn't it.

90
00:04:22.720 --> 00:04:27.000
<v Speaker 1>Swift is called statically strongly typed. Sounds kind of strict.

91
00:04:27.040 --> 00:04:28.720
<v Speaker 1>What does that actually mean when you're coding?

92
00:04:29.040 --> 00:04:32.120
<v Speaker 2>It means two key things. Statically typed means the compiler

93
00:04:32.199 --> 00:04:35.319
<v Speaker 2>must know the exact type of every variable and constant.

94
00:04:35.399 --> 00:04:38.480
<v Speaker 2>Is it an integer, a string, a custom object for

95
00:04:38.600 --> 00:04:40.680
<v Speaker 2>the app even runs at compile time?

96
00:04:40.759 --> 00:04:42.560
<v Speaker 1>Okay, checks happen early, right.

97
00:04:42.839 --> 00:04:45.720
<v Speaker 2>And strongly typed means you can't play fast and loose

98
00:04:45.720 --> 00:04:48.160
<v Speaker 2>with those types. If you declare something as a string,

99
00:04:48.600 --> 00:04:51.040
<v Speaker 2>you can't suddenly decide to put a number and int

100
00:04:51.360 --> 00:04:51.839
<v Speaker 2>into it.

101
00:04:51.839 --> 00:04:54.399
<v Speaker 1>Later The compiler will just say nope.

102
00:04:53.839 --> 00:04:57.720
<v Speaker 2>Exactly compile time error. Swift wants to catch those kinds

103
00:04:57.759 --> 00:05:00.079
<v Speaker 2>of mistakes before they can cause crashes when a user

104
00:05:00.120 --> 00:05:02.399
<v Speaker 2>is running the app. But hang on, if it's static,

105
00:05:02.839 --> 00:05:04.680
<v Speaker 2>why don't I always have to write like let name

106
00:05:05.279 --> 00:05:08.399
<v Speaker 2>string alice. Sometimes I can just write let name alice

107
00:05:08.399 --> 00:05:09.800
<v Speaker 2>and it works. How does it know?

108
00:05:10.040 --> 00:05:13.480
<v Speaker 1>Ah? That's the magic of type inference. Swift is clever

109
00:05:13.639 --> 00:05:15.639
<v Speaker 1>enough in many cases to look at the value you're

110
00:05:15.639 --> 00:05:19.120
<v Speaker 1>assigning initially and infer or deduce.

111
00:05:19.040 --> 00:05:20.920
<v Speaker 2>The type It guess is the type.

112
00:05:21.120 --> 00:05:23.839
<v Speaker 1>It makes an educated guess based on the value. If

113
00:05:23.920 --> 00:05:26.720
<v Speaker 1>you write alice, it knows that's a string. If you

114
00:05:26.759 --> 00:05:29.360
<v Speaker 1>write ten, it knows that's an int. You get the conciseness,

115
00:05:29.480 --> 00:05:31.759
<v Speaker 1>But the key thing is the type is still figured

116
00:05:31.759 --> 00:05:34.319
<v Speaker 1>out and locked in at compile time, it's still static

117
00:05:34.319 --> 00:05:34.800
<v Speaker 1>and strong.

118
00:05:35.079 --> 00:05:38.639
<v Speaker 2>Okay, that makes sense. So Swift is strict about types.

119
00:05:39.079 --> 00:05:42.560
<v Speaker 2>That brings up a huge historical problem in programming. What

120
00:05:42.680 --> 00:05:48.600
<v Speaker 2>about missing values, null pointers, undefined the billion dollar mistake? Right?

121
00:05:49.319 --> 00:05:52.519
<v Speaker 2>How does Swift handle needing to represent nothing?

122
00:05:52.759 --> 00:05:56.560
<v Speaker 1>This is one of Swift's absolute killer features. Optionals indicated

123
00:05:56.600 --> 00:05:57.920
<v Speaker 1>by that question mark after.

124
00:05:57.800 --> 00:06:00.319
<v Speaker 2>A type like string or int exactly.

125
00:06:00.120 --> 00:06:02.560
<v Speaker 1>And optional is like a little box. It might contain

126
00:06:02.600 --> 00:06:05.160
<v Speaker 1>a value of the specified type, like a string, or

127
00:06:05.199 --> 00:06:07.480
<v Speaker 1>it might contain nil, which is Swift's way of saying

128
00:06:07.680 --> 00:06:10.600
<v Speaker 1>no value here. And the crucial difference.

129
00:06:10.199 --> 00:06:13.079
<v Speaker 2>Is the crucial difference is that the type system knows

130
00:06:13.120 --> 00:06:17.079
<v Speaker 2>about the possibility of nil. A regular string cannot be nil.

131
00:06:17.240 --> 00:06:21.600
<v Speaker 2>A string can be nil. It forces you, the developer,

132
00:06:21.800 --> 00:06:25.399
<v Speaker 2>to explicitly deal with the possibility that the value might

133
00:06:25.439 --> 00:06:25.959
<v Speaker 2>be missing.

134
00:06:26.079 --> 00:06:28.000
<v Speaker 1>You can't just use it directly assuming it's there.

135
00:06:28.079 --> 00:06:30.480
<v Speaker 2>Nope, you have to unwrap it, check if the box

136
00:06:30.519 --> 00:06:32.959
<v Speaker 2>has something inside before you try to use it. Now

137
00:06:33.000 --> 00:06:36.040
<v Speaker 2>you can force unwrap with an exclamation mark.

138
00:06:35.879 --> 00:06:37.439
<v Speaker 1>Which everyone says is dangerous.

139
00:06:37.519 --> 00:06:39.759
<v Speaker 2>It is. It's like saying, I swear this isn't nil.

140
00:06:39.759 --> 00:06:44.319
<v Speaker 2>Trust me if you're wrong, your app crashes instantly, So yeah,

141
00:06:44.399 --> 00:06:47.519
<v Speaker 2>avoid it unless you are absolutely positively certain.

142
00:06:47.680 --> 00:06:49.519
<v Speaker 1>So what are the safe ways to unwrap?

143
00:06:49.639 --> 00:06:52.560
<v Speaker 2>The main safe ways are if let and guardlet Okay,

144
00:06:52.680 --> 00:06:55.800
<v Speaker 2>difference with if let you basically say, if this optional

145
00:06:55.839 --> 00:06:58.560
<v Speaker 2>contains a value, let's assign it to a temporary constant

146
00:06:58.600 --> 00:07:01.959
<v Speaker 2>and then run this block of code. That unwrapped constant

147
00:07:02.000 --> 00:07:05.720
<v Speaker 2>is only usable inside the fin if blocks curly braces.

148
00:07:05.399 --> 00:07:08.519
<v Speaker 1>So it's very contained, like a little safe zone exactly.

149
00:07:08.959 --> 00:07:13.120
<v Speaker 2>Now. Guard let is often preferred, especially inside functions. It

150
00:07:13.160 --> 00:07:15.160
<v Speaker 2>works kind of like a bouncer at a club. You

151
00:07:15.319 --> 00:07:18.160
<v Speaker 2>use guardlet to check preconditions. At the start of a function,

152
00:07:18.879 --> 00:07:21.720
<v Speaker 2>guard that we have a value here. If we don't.

153
00:07:21.879 --> 00:07:25.720
<v Speaker 2>If it's nil, then we must exit immediately. The else

154
00:07:25.800 --> 00:07:28.920
<v Speaker 2>block of a guard statement has to exit the current scope,

155
00:07:29.079 --> 00:07:30.360
<v Speaker 2>usually with return or.

156
00:07:30.279 --> 00:07:32.879
<v Speaker 1>Throw, So it's for checking requirements early on.

157
00:07:32.879 --> 00:07:36.839
<v Speaker 2>Precisely, and the big advantages. If the guardlet check passes,

158
00:07:37.040 --> 00:07:40.759
<v Speaker 2>meaning the optional did have a value, the unwrapped constant

159
00:07:40.800 --> 00:07:43.800
<v Speaker 2>is available for use throughout the entire rest of the function,

160
00:07:44.199 --> 00:07:45.600
<v Speaker 2>not just in a nested.

161
00:07:45.319 --> 00:07:49.639
<v Speaker 1>Block that avoids nesting. If it's deeper and deeper, the

162
00:07:49.680 --> 00:07:53.120
<v Speaker 1>pyramid of doom. Exactly guard let keeps your code flatter,

163
00:07:53.319 --> 00:07:57.279
<v Speaker 1>clear and enforces that fail fast mentality. If inputs aren't valid,

164
00:07:57.759 --> 00:08:00.639
<v Speaker 1>it's generally considered cleaner for handling requires options.

165
00:08:00.879 --> 00:08:03.120
<v Speaker 2>That's a really clear explanation. It forces you to be

166
00:08:03.160 --> 00:08:06.279
<v Speaker 2>honest about missing data. Okay, Moving up a level from

167
00:08:06.360 --> 00:08:09.480
<v Speaker 2>individual values, how do we organize code into bigger chunks.

168
00:08:09.480 --> 00:08:12.959
<v Speaker 2>We have struct and class. Big difference there, right, value

169
00:08:13.040 --> 00:08:14.199
<v Speaker 2>versus reference types.

170
00:08:14.360 --> 00:08:17.439
<v Speaker 1>Huge difference, probably one of the most fundamental distinctions in Swift.

171
00:08:17.639 --> 00:08:20.480
<v Speaker 1>Let's start with structures. Struct Yeah, there are value types.

172
00:08:20.800 --> 00:08:23.720
<v Speaker 2>Meaning when you pass a struct around, assign it to

173
00:08:23.759 --> 00:08:26.360
<v Speaker 2>a new variable, pass it into a function, you are

174
00:08:26.399 --> 00:08:28.439
<v Speaker 2>always working with a copy of the data. Think of

175
00:08:28.480 --> 00:08:30.040
<v Speaker 2>it like making a photocopy.

176
00:08:30.279 --> 00:08:32.519
<v Speaker 1>Changing the copy doesn't affect the original.

177
00:08:32.480 --> 00:08:36.559
<v Speaker 2>Not at all. They are completely independent. Plus, structs get

178
00:08:36.559 --> 00:08:40.559
<v Speaker 2>a handy default initializer called the member wise initializer for free,

179
00:08:40.679 --> 00:08:41.360
<v Speaker 2>which is nice.

180
00:08:41.440 --> 00:08:44.840
<v Speaker 1>Okay, So structs are copies. What about classes? Class?

181
00:08:45.120 --> 00:08:48.799
<v Speaker 2>Classes are reference types. Think of this like sharing a

182
00:08:48.840 --> 00:08:51.519
<v Speaker 2>link to a Google doc instead of emailing a word file.

183
00:08:52.080 --> 00:08:54.679
<v Speaker 2>If you have a variable holding a class instance and

184
00:08:54.720 --> 00:08:58.519
<v Speaker 2>you assign that to another variable, both variables now point

185
00:08:58.559 --> 00:09:00.320
<v Speaker 2>to the exact same object in.

186
00:09:00.320 --> 00:09:03.080
<v Speaker 1>Memory, so if one variable changes.

187
00:09:02.720 --> 00:09:05.840
<v Speaker 2>Something, the other one sees the change immediately because they're

188
00:09:05.840 --> 00:09:10.799
<v Speaker 2>both looking at the same underlying instance. Classes also support inheritance,

189
00:09:10.879 --> 00:09:15.320
<v Speaker 2>which structs don't. But this shared nature brings complexity, especially

190
00:09:15.360 --> 00:09:17.759
<v Speaker 2>with memory management, which we'll get to right.

191
00:09:17.919 --> 00:09:21.960
<v Speaker 1>I often hear the advice prefers structs over classes that

192
00:09:22.080 --> 00:09:22.919
<v Speaker 1>generally sound.

193
00:09:23.240 --> 00:09:26.039
<v Speaker 2>It's a very common and generally good rule of thumb

194
00:09:26.080 --> 00:09:29.519
<v Speaker 2>in swift development. Because value types strucks are copied, they

195
00:09:29.559 --> 00:09:32.399
<v Speaker 2>are inherently simpler and safer. You don't have to worry

196
00:09:32.399 --> 00:09:35.320
<v Speaker 2>about side effects some other part of your code unexpectedly

197
00:09:35.440 --> 00:09:38.840
<v Speaker 2>changing the data out from under You use structs unless

198
00:09:38.879 --> 00:09:42.120
<v Speaker 2>you specifically need. The shared reference behavior of classes or

199
00:09:42.159 --> 00:09:43.480
<v Speaker 2>inheritance makes sense.

200
00:09:43.919 --> 00:09:47.440
<v Speaker 1>Safety first again. Okay, let's shift to the visual side

201
00:09:47.440 --> 00:09:52.720
<v Speaker 1>the UI building interfaces for iPhones iPads, the screen sizes

202
00:09:52.759 --> 00:09:54.679
<v Speaker 1>are all over the place. You can't just say put

203
00:09:54.679 --> 00:09:57.679
<v Speaker 1>this button a pixel X pixel y right. That old

204
00:09:57.879 --> 00:10:00.639
<v Speaker 1>frame based layout seems impossible.

205
00:10:00.120 --> 00:10:02.639
<v Speaker 2>Now autoly impossible. It would break immediately on a different

206
00:10:02.639 --> 00:10:05.360
<v Speaker 2>device size or orientation. Apple solution is.

207
00:10:05.399 --> 00:10:08.600
<v Speaker 1>Auto layout, which uses constraints exactly.

208
00:10:08.960 --> 00:10:13.039
<v Speaker 2>Instead of giving fixed coordinates, you define rules relationships constraints

209
00:10:13.039 --> 00:10:14.519
<v Speaker 2>between UI elements, like.

210
00:10:14.480 --> 00:10:17.039
<v Speaker 1>This label should be eight points below that image.

211
00:10:16.840 --> 00:10:19.720
<v Speaker 2>View precisely, or this button should be centered horizontally in

212
00:10:19.759 --> 00:10:22.240
<v Speaker 2>its container, or these two text fields should have the

213
00:10:22.279 --> 00:10:26.000
<v Speaker 2>same width. You define the layout using these relationships, so.

214
00:10:25.919 --> 00:10:28.919
<v Speaker 1>You tell the system the rules, not the exact positions.

215
00:10:28.919 --> 00:10:31.519
<v Speaker 2>You got it, and then when the screen size changes

216
00:10:31.679 --> 00:10:35.399
<v Speaker 2>or the device rotates, the auto layout engine recalculates all

217
00:10:35.399 --> 00:10:38.279
<v Speaker 2>the frames based on the constraints you provided. It makes

218
00:10:38.360 --> 00:10:42.320
<v Speaker 2>adaptive layout possible. UIs that adapt gracefully to different environments.

219
00:10:42.519 --> 00:10:46.039
<v Speaker 1>And that ties into size classes, right that compact regular widthing.

220
00:10:46.399 --> 00:10:49.720
<v Speaker 2>Yeah. Size classes are a higher level abstraction Apple provides.

221
00:10:50.080 --> 00:10:53.600
<v Speaker 2>They group different device sizes and orientations into categories like

222
00:10:53.759 --> 00:10:56.919
<v Speaker 2>compact with regular height. You can then use these size

223
00:10:56.919 --> 00:10:59.480
<v Speaker 2>classes to provide different sets of constraints or even different

224
00:10:59.679 --> 00:11:03.480
<v Speaker 2>y or arrangements for say an iPhone in portrait versus

225
00:11:03.519 --> 00:11:06.639
<v Speaker 2>an iPad and landscape. It adds another layer to adaptivity.

226
00:11:06.720 --> 00:11:08.519
<v Speaker 1>Okay, this feel like we're building up the layers. We

227
00:11:08.559 --> 00:11:11.480
<v Speaker 1>have safe data types, ways to structure code ADAPTI VII.

228
00:11:12.039 --> 00:11:15.759
<v Speaker 1>But underlying all this, especially with classes, is memory. Things

229
00:11:15.799 --> 00:11:18.919
<v Speaker 1>get created, They take up space. How do they get

230
00:11:18.960 --> 00:11:20.200
<v Speaker 1>cleaned up? What's the mechanism.

231
00:11:20.279 --> 00:11:23.720
<v Speaker 2>The mechanism is automatic reference Counting or ARC.

232
00:11:24.240 --> 00:11:26.360
<v Speaker 1>ARC, not garbage collection like in Java.

233
00:11:26.480 --> 00:11:30.480
<v Speaker 2>No, it's different. ARC isn't a separate process that periodically

234
00:11:30.559 --> 00:11:34.519
<v Speaker 2>scans memory. It's more of a compile time feature where

235
00:11:34.639 --> 00:11:38.559
<v Speaker 2>swift automatically inserts memory management code, retain and release calls

236
00:11:38.720 --> 00:11:40.159
<v Speaker 2>into your compiled program.

237
00:11:40.240 --> 00:11:42.080
<v Speaker 1>And it only cares about certain types.

238
00:11:42.480 --> 00:11:47.519
<v Speaker 2>Crucially, yes, ARC only manages memory for instances of classes

239
00:11:47.960 --> 00:11:50.840
<v Speaker 2>reference types. It doesn't need to worry about structs or

240
00:11:51.120 --> 00:11:54.960
<v Speaker 2>enoms value types because they are copied and their memory

241
00:11:55.000 --> 00:11:57.720
<v Speaker 2>is handled automatically when they go out of scope. It's

242
00:11:57.759 --> 00:12:01.879
<v Speaker 2>only the shared referenced class in instances that need explicit counting.

243
00:12:02.000 --> 00:12:04.759
<v Speaker 1>Okay, so how does this counting work? How does ARC

244
00:12:04.840 --> 00:12:07.080
<v Speaker 1>know when it's safe to get rid of a class instance.

245
00:12:07.399 --> 00:12:10.039
<v Speaker 2>It keeps a reference count for each class instance. When

246
00:12:10.080 --> 00:12:12.440
<v Speaker 2>you create an instance and assign it to a variable

247
00:12:12.519 --> 00:12:15.279
<v Speaker 2>or constant, that creates a strong reference.

248
00:12:14.919 --> 00:12:16.720
<v Speaker 1>By default strong reference, and.

249
00:12:16.679 --> 00:12:20.080
<v Speaker 2>That increments the instance's reference count, usually from zero to one.

250
00:12:20.320 --> 00:12:22.720
<v Speaker 2>If you assign that same instance to another variable, the

251
00:12:22.759 --> 00:12:24.039
<v Speaker 2>count goes up again to two.

252
00:12:24.159 --> 00:12:26.840
<v Speaker 1>So it counts how many variables are actively pointing to it.

253
00:12:27.200 --> 00:12:29.639
<v Speaker 2>Basically, yes, how many owners it has? You could say,

254
00:12:29.960 --> 00:12:32.399
<v Speaker 2>as long as that reference count is greater than zero.

255
00:12:32.960 --> 00:12:35.279
<v Speaker 2>ARC knows the instance is still needed, so it keeps

256
00:12:35.320 --> 00:12:35.919
<v Speaker 2>it in memory.

257
00:12:36.120 --> 00:12:37.440
<v Speaker 1>And when does it get deallocated?

258
00:12:37.799 --> 00:12:41.080
<v Speaker 2>When the last strong reference to it is removed? Maybe

259
00:12:41.080 --> 00:12:43.600
<v Speaker 2>a variable goes out of scope, or you explicitly set

260
00:12:43.639 --> 00:12:47.480
<v Speaker 2>it to nil, the reference count drops when it hits zero,

261
00:12:48.000 --> 00:12:51.360
<v Speaker 2>ARC knows nothing is using the instance anymore and immediately

262
00:12:51.399 --> 00:12:53.159
<v Speaker 2>deallocates it, freeing up the memory.

263
00:12:53.240 --> 00:12:57.240
<v Speaker 1>Okay, seems straightforward enough, But there's a catch, right the

264
00:12:57.240 --> 00:12:59.159
<v Speaker 1>infamous strong retained cycle.

265
00:12:59.320 --> 00:13:03.480
<v Speaker 2>Ah yeah, yes, the classic memory leak scenario. In reference

266
00:13:03.519 --> 00:13:08.000
<v Speaker 2>counted systems. This happens when two or more class instances

267
00:13:08.159 --> 00:13:09.559
<v Speaker 2>hold strong references to.

268
00:13:09.559 --> 00:13:11.279
<v Speaker 1>Each other, like a circular dependency.

269
00:13:11.399 --> 00:13:14.519
<v Speaker 2>Exactly. Imagine a person class that has a property for

270
00:13:14.559 --> 00:13:17.519
<v Speaker 2>their apartment and the apartment class has a property for

271
00:13:17.559 --> 00:13:21.840
<v Speaker 2>its tenant, the person. If both those properties are default strong.

272
00:13:21.559 --> 00:13:23.200
<v Speaker 1>References, they're holding on to each other.

273
00:13:23.440 --> 00:13:27.559
<v Speaker 2>Precisely, the person keeps the apartment alive reference count one,

274
00:13:27.639 --> 00:13:30.399
<v Speaker 2>and the apartment keeps the person alive reference count one,

275
00:13:30.639 --> 00:13:32.679
<v Speaker 2>even if nothing else in your app points to either

276
00:13:32.720 --> 00:13:36.799
<v Speaker 2>the person or the apartment anymore. Their mutual strong references

277
00:13:36.879 --> 00:13:38.759
<v Speaker 2>keep their counts from ever reaching.

278
00:13:38.480 --> 00:13:41.399
<v Speaker 1>Zero, so they just stay in memory forever leaking.

279
00:13:41.720 --> 00:13:44.919
<v Speaker 2>Yep, memory leak. ARC can't clean them up because their

280
00:13:44.960 --> 00:13:46.240
<v Speaker 2>counts never drop to zero.

281
00:13:46.679 --> 00:13:49.159
<v Speaker 1>Okay, so how do we break these cycles? We need

282
00:13:49.200 --> 00:13:51.360
<v Speaker 1>a reference that doesn't increase the count, right.

283
00:13:51.679 --> 00:13:54.399
<v Speaker 2>We need to tell AARC, hey, this link exists, but

284
00:13:54.480 --> 00:13:57.759
<v Speaker 2>don't count it towards keeping the object alive and swift

285
00:13:57.759 --> 00:14:02.000
<v Speaker 2>gives us two ways to do this and unowned references

286
00:14:02.320 --> 00:14:03.240
<v Speaker 2>week and unowned.

287
00:14:03.279 --> 00:14:05.000
<v Speaker 1>What's the difference when do you use which?

288
00:14:05.720 --> 00:14:09.120
<v Speaker 2>The choice depends entirely on whether the reference could legitimately

289
00:14:09.159 --> 00:14:12.519
<v Speaker 2>become nil during its lifetime. You use weak, usually written

290
00:14:12.559 --> 00:14:15.879
<v Speaker 2>weekvar when the other instance might be deallocated before the

291
00:14:15.919 --> 00:14:17.200
<v Speaker 2>instance holding their reference.

292
00:14:17.240 --> 00:14:19.799
<v Speaker 1>So the reference itself needs to be able to become nil.

293
00:14:19.840 --> 00:14:24.159
<v Speaker 2>Exactly because the thing it points to might disappear. This

294
00:14:24.279 --> 00:14:28.639
<v Speaker 2>means weak references must always be declared as optional types

295
00:14:29.240 --> 00:14:33.919
<v Speaker 2>like weak var delegate my delegate. The class example is

296
00:14:34.000 --> 00:14:36.879
<v Speaker 2>a delegate pattern. A child object shouldn't keep its parent

297
00:14:36.879 --> 00:14:39.720
<v Speaker 2>controller alive, so the reference back to the delegate is

298
00:14:39.759 --> 00:14:40.399
<v Speaker 2>often weak.

299
00:14:40.559 --> 00:14:43.759
<v Speaker 1>Okay, Week means it can be nil, so it must

300
00:14:43.799 --> 00:14:45.600
<v Speaker 1>be optional. What about unowned?

301
00:14:46.000 --> 00:14:49.480
<v Speaker 2>You use unowned when you can guarantee, absolutely guarantee that

302
00:14:49.519 --> 00:14:52.039
<v Speaker 2>the reference will never be nil during the time you're

303
00:14:52.120 --> 00:14:55.559
<v Speaker 2>using it. The other instance will definitely outlive or live

304
00:14:55.600 --> 00:14:58.240
<v Speaker 2>exactly as long as the instance holding the reference.

305
00:14:58.279 --> 00:14:59.960
<v Speaker 1>But you're making a promise to the compiler.

306
00:15:00.120 --> 00:15:03.440
<v Speaker 2>You are because unowned references are assumed to always point

307
00:15:03.440 --> 00:15:06.200
<v Speaker 2>to something valid, they are not optionals. Think of our

308
00:15:06.279 --> 00:15:08.759
<v Speaker 2>person apartment example. Maybe an apartment must always have a

309
00:15:08.759 --> 00:15:11.639
<v Speaker 2>tenant while it exists in our system, the apartment's reference

310
00:15:11.639 --> 00:15:14.039
<v Speaker 2>back to the person could potentially be unowned.

311
00:15:14.279 --> 00:15:17.720
<v Speaker 1>What happens if you're wrong If you use unowned and

312
00:15:17.799 --> 00:15:20.639
<v Speaker 1>the other instance does get deallocated crash.

313
00:15:20.799 --> 00:15:23.159
<v Speaker 2>If you try to access an unowned reference after the

314
00:15:23.240 --> 00:15:27.159
<v Speaker 2>instance it ports too has been deallocated, your app will crash.

315
00:15:27.320 --> 00:15:29.759
<v Speaker 2>So you use unowned for that slight performance gain. No

316
00:15:29.879 --> 00:15:33.519
<v Speaker 2>optional unwrapping only when the relationship guarantees non n illness.

317
00:15:33.799 --> 00:15:36.080
<v Speaker 2>Weak is generally safer. If there's any.

318
00:15:35.919 --> 00:15:38.720
<v Speaker 1>Doubt, well, okay, that's a deep dive into memory. So

319
00:15:38.759 --> 00:15:42.240
<v Speaker 1>summarizing the pillars, we've got language levels, safety with let

320
00:15:42.360 --> 00:15:45.919
<v Speaker 1>var and strong typing crash prevention with optionals and safe

321
00:15:46.000 --> 00:15:50.240
<v Speaker 1>unwrapping like guardlet structure with value types, struct and reference types,

322
00:15:50.399 --> 00:15:54.480
<v Speaker 1>class adaptive UI with auto layout and constraints, and finally

323
00:15:54.759 --> 00:15:58.799
<v Speaker 1>managing class memory carefully with ARC using weak or unowned

324
00:15:58.840 --> 00:15:59.960
<v Speaker 1>to prevent retained cycles.

325
00:16:00.399 --> 00:16:04.279
<v Speaker 2>That really covers the foundational philosophy. Getting these concepts, especially

326
00:16:04.360 --> 00:16:07.519
<v Speaker 2>optionals in ARC, is what separates developers who write robust,

327
00:16:07.600 --> 00:16:09.960
<v Speaker 2>stable apps from those whose apps might be prone to

328
00:16:09.960 --> 00:16:11.559
<v Speaker 2>crashes or unexpected behavior.

329
00:16:12.000 --> 00:16:15.559
<v Speaker 1>So, with this foundation laid, where does this lead us?

330
00:16:15.919 --> 00:16:19.320
<v Speaker 1>For years, iOS development mostly used imperative programming for UI,

331
00:16:19.480 --> 00:16:23.039
<v Speaker 1>right like with UIKit and patterns like MVC. We were

332
00:16:23.039 --> 00:16:24.799
<v Speaker 1>telling the system how to change the view step by

333
00:16:24.799 --> 00:16:25.799
<v Speaker 1>step exactly.

334
00:16:25.840 --> 00:16:28.080
<v Speaker 2>You'd get some data, and then you'd write code to

335
00:16:28.120 --> 00:16:31.000
<v Speaker 2>find the label on the screen and manually update its

336
00:16:31.039 --> 00:16:34.120
<v Speaker 2>text property, find the image view and set its image,

337
00:16:34.159 --> 00:16:36.399
<v Speaker 2>and so on, very step by step instructions.

338
00:16:36.480 --> 00:16:40.519
<v Speaker 1>But the wind is shifting, isn't it towards something more declarative?

339
00:16:40.720 --> 00:16:45.000
<v Speaker 2>Massively shifting the new standard Swift UI flicks the model completely.

340
00:16:45.039 --> 00:16:48.799
<v Speaker 2>It uses declarative programming, meaning instead of telling the system

341
00:16:48.879 --> 00:16:52.279
<v Speaker 2>how to update the UI piece by piece, you simply

342
00:16:52.320 --> 00:16:54.759
<v Speaker 2>declare what the UI should look like for any given

343
00:16:54.799 --> 00:16:55.879
<v Speaker 2>state of your data.

344
00:16:55.919 --> 00:16:59.039
<v Speaker 1>So you define the end result for each state precisely.

345
00:16:59.080 --> 00:17:01.840
<v Speaker 2>You say, the data looks like this, the screen should

346
00:17:01.879 --> 00:17:05.119
<v Speaker 2>look like that, and you do this for all possible states.

347
00:17:05.640 --> 00:17:08.039
<v Speaker 2>Swift UI then figures out the most efficient way to

348
00:17:08.079 --> 00:17:11.240
<v Speaker 2>transition between those states automatically when the data changes. You

349
00:17:11.240 --> 00:17:13.359
<v Speaker 2>don't manage the individual updates anymore.

350
00:17:13.880 --> 00:17:17.680
<v Speaker 1>That sounds like a fundamental paradigm shift less manual control.

351
00:17:18.039 --> 00:17:19.839
<v Speaker 1>More describing the outcome.

352
00:17:19.640 --> 00:17:23.559
<v Speaker 2>It absolutely is. And understanding the imperative world of UIKit

353
00:17:23.839 --> 00:17:28.240
<v Speaker 2>and the principles we discussed today, especially type safety, value types,

354
00:17:28.319 --> 00:17:32.400
<v Speaker 2>and immutability, actually provides the perfect grounding to appreciate why

355
00:17:32.440 --> 00:17:36.160
<v Speaker 2>the declarative approach of swift UI is so powerful and efficient.

356
00:17:36.599 --> 00:17:39.559
<v Speaker 2>It builds directly on those core swift philosophies.

357
00:17:39.799 --> 00:17:43.359
<v Speaker 1>So a provocative thought for listeners. Yeah, master these fundamentals

358
00:17:43.359 --> 00:17:46.000
<v Speaker 1>the imperative way things were done, because it prepares you

359
00:17:46.039 --> 00:17:49.480
<v Speaker 1>perfectly for the declarative way things are going. Explore youikit,

360
00:17:49.839 --> 00:17:52.599
<v Speaker 1>understand arc and then get ready for swift UI.

361
00:17:52.680 --> 00:17:54.680
<v Speaker 2>Couldn't have sent it better myself. That's the journey.

362
00:17:54.799 --> 00:17:57.880
<v Speaker 1>Excellent. A lot to digest there, but absolutely crucial knowledge

363
00:17:57.920 --> 00:17:59.119
<v Speaker 1>that wraps up this deep dive
