Skip to content

Commit 7520e28

Browse files
committed
Fix broken references to migrated images containing a '.' in the name
1 parent 3e7fd66 commit 7520e28

4 files changed

Lines changed: 48 additions & 48 deletions

File tree

Sources/WWDCNotes/WWDCNotes.docc/WWDC23/WWDC23-10153-Unlock-the-power-of-grammatical-agreement.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ let size = AttributedString(localized: "small", options: options)
5555

5656
![][neutral]
5757

58-
[neutral]: WWDC23-10153-TermsOfAddress
58+
[neutral]: WWDC23-10153-TermsOfAddress.neutral
5959

6060
- New `referenceConcept` attribute in agreement, like `"\(person.name) is on ^[their](referentConcept: 1) way."`
6161
- You can provide custom `TermOfAddress` using `TermOfAddress.localized(language:pronouns:)` and pass array of `Mophology.Pronoun`

Sources/WWDCNotes/WWDCNotes.docc/WWDC23/WWDC23-10158-Animate-with-springs.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,17 @@ A spring can start with any initial velocity, so we get a natural feeling. Swift
3636

3737
![][1]
3838

39-
[1]: WWDC23-10158-Screenshot_2023-06-11_at_18
39+
[1]: WWDC23-10158-Screenshot_2023-06-11_at_18.39.10
4040

4141
Apple has been refining a new way to configure springs that's easier to understand and to work with. It uses just 2 parameters: duration and bounce. Increasing the duration makes the animation take longer. And increasing the bounce adds bounce to the animation. All of their frameworks that support springs will use them.
4242

4343
![][2]
4444

45-
[2]: WWDC23-10158-Screenshot_2023-06-11_at_18
45+
[2]: WWDC23-10158-Screenshot_2023-06-11_at_18.40.29
4646

4747
![][3]
4848

49-
[3]: WWDC23-10158-Screenshot_2023-06-11_at_18
49+
[3]: WWDC23-10158-Screenshot_2023-06-11_at_18.43.40
5050

5151
Being able to understand the math that's behind these curves helps make springs feel more approachable, but if math just makes your head spin, don't worry, it's completely optional. They’ve implemented all of this math for you.
5252

@@ -123,7 +123,7 @@ But if you really want to do a conversion yourself, here are the three equations
123123

124124
![][4]
125125

126-
[4]: WWDC23-10158-Screenshot_2023-06-11_at_19
126+
[4]: WWDC23-10158-Screenshot_2023-06-11_at_19.07.03
127127

128128
You can call value to get the position of the spring. You just pass in a target, which is what the spring is moving towards, and the time you want to evaluate it at. You can also use the same inputs on a velocity method to evaluate the spring's velocity over time.
129129

Sources/WWDCNotes/WWDCNotes.docc/WWDC23/WWDC23-10248-Analyze-hangs-with-Instruments.md

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ When dealing with hangs, there’re three steps you need to follow; find a hang,
2020

2121
![][1]
2222

23-
[1]: WWDC23-10248-Screenshot_2023-06-10_at_13
23+
[1]: WWDC23-10248-Screenshot_2023-06-10_at_13.43.22
2424

2525
Hang == Delay. What kind of delay is acceptable depends on the circumstances.
2626

2727
![][2]
2828

29-
[2]: WWDC23-10248-Screenshot_2023-06-10_at_13
29+
[2]: WWDC23-10248-Screenshot_2023-06-10_at_13.52.45
3030

3131
For a discrete interaction, a delay below
3232

@@ -40,47 +40,47 @@ Delay above 250ms doesn’t feel instant anymore. That’s why most of instrumen
4040

4141
![][3]
4242

43-
[3]: WWDC23-10248-Screenshot_2023-06-10_at_13
43+
[3]: WWDC23-10248-Screenshot_2023-06-10_at_13.53.31
4444

4545
To enable our UI elements to react “instantly”, it is vital to keep the main thread free from non-UI work.
4646

4747
# Event handling and rendering loop
4848

4949
![][4]
5050

51-
[4]: WWDC23-10248-Screenshot_2023-06-10_at_13
51+
[4]: WWDC23-10248-Screenshot_2023-06-10_at_13.57.14
5252

5353
Given that every update to a UI element needs some time on the main thread, and we want these updates to happen within 100 ms to feel real. Ideally, **no work on the main thread should take longer than 100 ms**. If you can be faster, even better. Long-running work on the main thread can also cause hitches.
5454

5555
# Profiling your app on Xcode
5656

5757
![][5]
5858

59-
[5]: WWDC23-10248-Screenshot_2023-06-10_at_14
59+
[5]: WWDC23-10248-Screenshot_2023-06-10_at_14.01.42
6060

6161
Shortly, Xcode will install your app on device, but, it will not launch it. Instead, you will see an instrument template chooser on your screen. Choose “Time Profiler”. Time profiler is a good starting point if you don’t yet know what you are looking for and want to get a better understanding of what your app is doing.
6262

6363
![][6]
6464

65-
[6]: WWDC23-10248-Screenshot_2023-06-10_at_14
65+
[6]: WWDC23-10248-Screenshot_2023-06-10_at_14.02.24
6666

6767
It will create a new time profiler document, which includes time profiler and hangs profiler, both of which will be useful for addressing hangs.
6868

6969
![][7]
7070

71-
[7]: WWDC23-10248-Screenshot_2023-06-10_at_14
71+
[7]: WWDC23-10248-Screenshot_2023-06-10_at_14.05.29
7272

7373
Hit record button at the top-left of the tool bar. It will launch the configured application and start capturing data. And use you app as you normally would. Instruments will record all of your app’s data. Once you found the hang, hit the stop recording button in the toolbar. In this talk, he used Backyard Birds app to demonstrate hangs.
7474

7575
![][8]
7676

77-
[8]: WWDC23-10248-Screenshot_2023-06-10_at_14
77+
[8]: WWDC23-10248-Screenshot_2023-06-10_at_14.11.23
7878

7979
Instruments has also detected the hang. It measures the hang duration, and labels the corresponding intervals according to the severity. In this case, instruments shows us a “Server Hang” has happened (see above screenshot).
8080

8181
![][9]
8282

83-
[9]: WWDC23-10248-Screenshot_2023-06-10_at_14
83+
[9]: WWDC23-10248-Screenshot_2023-06-10_at_14.16.11
8484

8585
There are two main cases for an unresponsive main thread:
8686

@@ -89,37 +89,37 @@ There are two main cases for an unresponsive main thread:
8989

9090
![][10]
9191

92-
[10]: WWDC23-10248-Screenshot_2023-06-10_at_14
92+
[10]: WWDC23-10248-Screenshot_2023-06-10_at_14.20.54
9393

9494
In order to identify the hang, first select the Backyard Birds on the left panel, tap the disclosure indicator to unfold all the threads, select main thread, then click to the ugly red area (hang-interval in the timeline) to show the context menu, hold option key and click “Set inspection range and zoom” (as shown in the above screenshot).
9595

9696
![][11]
9797

98-
[11]: WWDC23-10248-Screenshot_2023-06-10_at_14
98+
[11]: WWDC23-10248-Screenshot_2023-06-10_at_14.22.09
9999

100100
This zooms into the interval’s range and filters the data displayed in the detail view to the selected time range.
101101

102102
![][12]
103103

104-
[12]: WWDC23-10248-Screenshot_2023-06-10_at_14
104+
[12]: WWDC23-10248-Screenshot_2023-06-10_at_14.25.01
105105

106106
![][13]
107107

108-
[13]: WWDC23-10248-Screenshot_2023-06-10_at_14
108+
[13]: WWDC23-10248-Screenshot_2023-06-10_at_14.25.19
109109

110110
After you have done above two steps, it will filter out all functions from the system libraries, making it a lot easier for you to inspect just on your hanging code.
111111

112112
As you can see, the `BackgroundThumbnailView.body.getter` takes the longest. It is the Busy Main Thread problem. There are two potential scenarios to cause this hang.
113113

114114
![][14]
115115

116-
[14]: WWDC23-10248-Screenshot_2023-06-10_at_14
116+
[14]: WWDC23-10248-Screenshot_2023-06-10_at_14.27.33
117117

118118
How we should reduce the work on the main thread depends on which case we have.
119119

120120
![][15]
121121

122-
[15]: WWDC23-10248-Screenshot_2023-06-10_at_14
122+
[15]: WWDC23-10248-Screenshot_2023-06-10_at_14.32.46
123123

124124
For a long running function, we want to look at its implementation and its callees. We need to look further down.
125125

@@ -131,142 +131,142 @@ To measure the executing time of a specific function, use os_signposts. Let’s
131131

132132
![][16]
133133

134-
[16]: WWDC23-10248-Screenshot_2023-06-10_at_14
134+
[16]: WWDC23-10248-Screenshot_2023-06-10_at_14.36.27
135135

136136
Click the view body instrument and drag it into the document window to add it. We gotta record again.
137137

138138
![][17]
139139

140-
[17]: WWDC23-10248-Screenshot_2023-06-10_at_14
140+
[17]: WWDC23-10248-Screenshot_2023-06-10_at_14.38.10
141141

142142
![][18]
143143

144-
[18]: WWDC23-10248-Screenshot_2023-06-10_at_14
144+
[18]: WWDC23-10248-Screenshot_2023-06-10_at_14.39.27
145145

146146
You can see a lot of orange intervals all labelled BackgroundThumbnailView. This tells us precisely how many body executions there were and how long each one took. The orange color indicates that the runtime of that specific body execution took a little longer than what we are aiming for with SwiftUI. The bigger problem is how many intervals there are.
147147

148148
![][19]
149149

150-
[19]: WWDC23-10248-Screenshot_2023-06-10_at_14
150+
[19]: WWDC23-10248-Screenshot_2023-06-10_at_14.42.43
151151

152152
![][20]
153153

154-
[20]: WWDC23-10248-Screenshot_2023-06-10_at_14
154+
[20]: WWDC23-10248-Screenshot_2023-06-10_at_14.43.34
155155

156156
We can now address to that problematic code.
157157

158158
![][21]
159159

160-
[21]: WWDC23-10248-Screenshot_2023-06-10_at_14
160+
[21]: WWDC23-10248-Screenshot_2023-06-10_at_14.44.53
161161

162162
Let’s just use lazy VGrid to solve the issue.
163163

164164
![][22]
165165

166-
[22]: WWDC23-10248-Screenshot_2023-06-10_at_14
166+
[22]: WWDC23-10248-Screenshot_2023-06-10_at_14.45.42
167167

168168
Let’s profile the updated code.
169169

170170
![][23]
171171

172-
[23]: WWDC23-10248-Screenshot_2023-06-10_at_14
172+
[23]: WWDC23-10248-Screenshot_2023-06-10_at_14.47.36
173173

174174
We still have a micro-hang. Let’s profile it on our iPad.
175175

176176
![][24]
177177

178-
[24]: WWDC23-10248-Screenshot_2023-06-10_at_14
178+
[24]: WWDC23-10248-Screenshot_2023-06-10_at_14.49.10
179179

180180
We still experience the hang on iPad. That’s because now our screen is bigger and there’re a lot more thumbnails to be rendered. Instruments also recorded this hang (see in below screenshot). We see more BackgroundThumbnailView bodies again.
181181

182182
![][25]
183183

184-
[25]: WWDC23-10248-Screenshot_2023-06-10_at_14
184+
[25]: WWDC23-10248-Screenshot_2023-06-10_at_14.51.57
185185

186186
The same code performed mostly OK on an iPhone but was slow on an iPad, simply because the screen was bigger. This is one of the reasons why you should also fix micro hangs. Let’s find out what we can do to make each individual execution faster.
187187

188188
![][26]
189189

190-
[26]: WWDC23-10248-Screenshot_2023-06-10_at_15
190+
[26]: WWDC23-10248-Screenshot_2023-06-10_at_15.20.39
191191

192192
We seem to be computing a thumbnail on the fly here, which is quite time consuming. This is work we should rather be doing in the background and not keep the main thread busy with. To better understand what change we can make, let’s look at the context how the thumbnail getter is called.
193193

194194
![][27]
195195

196-
[27]: WWDC23-10248-Screenshot_2023-06-10_at_15
196+
[27]: WWDC23-10248-Screenshot_2023-06-10_at_15.23.44
197197

198198
![][28]
199199

200-
[28]: WWDC23-10248-Screenshot_2023-06-10_at_15
200+
[28]: WWDC23-10248-Screenshot_2023-06-10_at_15.24.02
201201

202202
![][29]
203203

204-
[29]: WWDC23-10248-Screenshot_2023-06-10_at_15
204+
[29]: WWDC23-10248-Screenshot_2023-06-10_at_15.24.59
205205

206206
And update our code to show progress view while loading the actual image.
207207

208208
![][30]
209209

210-
[30]: WWDC23-10248-Screenshot_2023-06-10_at_15
210+
[30]: WWDC23-10248-Screenshot_2023-06-10_at_15.26.20
211211

212212
Let’s try out the updated code. You will our progress indicators, and a few seconds later, our thumbnails were displayed.
213213

214214
![][31]
215215

216-
[31]: WWDC23-10248-Screenshot_2023-06-10_at_15
216+
[31]: WWDC23-10248-Screenshot_2023-06-10_at_15.28.43
217217

218218
This is the slightly different type of hangs. The way Instruments’ hang detection works is that it looks at all works items on the main thread and check whether they are too long. If so, it marks them as potential hang. Hang detection also detects these asynchronous or delayed cases, but it only measures the potential delay, not the actually experienced delay.
219219

220220
![][32]
221221

222-
[32]: WWDC23-10248-Screenshot_2023-06-10_at_15
222+
[32]: WWDC23-10248-Screenshot_2023-06-10_at_15.36.57
223223

224224
The problem (executing asynchronous task on main thread)
225225

226226
![][33]
227227

228-
[33]: WWDC23-10248-Screenshot_2023-06-10_at_15
228+
[33]: WWDC23-10248-Screenshot_2023-06-10_at_15.38.51
229229

230230
The solution
231231

232232
![][34]
233233

234-
[34]: WWDC23-10248-Screenshot_2023-06-10_at_15
234+
[34]: WWDC23-10248-Screenshot_2023-06-10_at_15.41.47
235235

236236
![][35]
237237

238-
[35]: WWDC23-10248-Screenshot_2023-06-10_at_15
238+
[35]: WWDC23-10248-Screenshot_2023-06-10_at_15.41.16
239239

240240
This should allow the “thumbnail” getter to execute on Swift Concurrency’s concurrent thread pool inside of the main thread. Let’s try it out again.
241241

242242
![][36]
243243

244-
[36]: WWDC23-10248-Screenshot_2023-06-10_at_15
244+
[36]: WWDC23-10248-Screenshot_2023-06-10_at_15.43.19
245245

246246
![][37]
247247

248-
[37]: WWDC23-10248-Screenshot_2023-06-10_at_15
248+
[37]: WWDC23-10248-Screenshot_2023-06-10_at_15.44.57
249249

250250
![][38]
251251

252-
[38]: WWDC23-10248-Screenshot_2023-06-10_at_15
252+
[38]: WWDC23-10248-Screenshot_2023-06-10_at_15.45.22
253253

254254
![][39]
255255

256-
[39]: WWDC23-10248-Screenshot_2023-06-10_at_15
256+
[39]: WWDC23-10248-Screenshot_2023-06-10_at_15.46.24
257257

258258
![][40]
259259

260-
[40]: WWDC23-10248-Screenshot_2023-06-10_at_15
260+
[40]: WWDC23-10248-Screenshot_2023-06-10_at_15.47.17
261261

262262
![][41]
263263

264-
[41]: WWDC23-10248-Screenshot_2023-06-10_at_15
264+
[41]: WWDC23-10248-Screenshot_2023-06-10_at_15.50.58
265265

266266
To determine whether a blocked thread is a responsiveness issue or not, look to the Hang instruments, not the thread states instruments. So a blocked main thread doesn’t imply an unresponsive main thread. High CPU usage also doesn’t imply that the main thread is unresponsive. If the main thread is unresponsive, that means it was either blocked or the main thread was busy.
267267

268268
![][42]
269269

270-
[42]: WWDC23-10248-Screenshot_2023-06-10_at_15
270+
[42]: WWDC23-10248-Screenshot_2023-06-10_at_15.53.57
271271

272272
Whatever work you are doing on the main thread, it should be done in less than 100ms to free the main thread for event handling again. The shorter the better. Determine whether the main thread is busy or blocked. Hangs can surface synchronously or asynchronously. Do less, move work to the background, sometimes, even both. measure first and check whether there is actually a hang before optimizing.

Sources/migrate-notes/main.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ for session in sessionByID.values {
7474

7575
sessionFileContents = sessionFileContents.replacing(
7676
"../../../images/notes/\(event.lowercased())/\(session.code)/\(imageFileName)",
77-
with: newImageFilePath.components(separatedBy: "/").last!.components(separatedBy: ".")[0]
77+
with: newImageFilePath.components(separatedBy: "/").last!.components(separatedBy: ".").dropLast().joined(separator: ".")
7878
)
7979
}
8080

0 commit comments

Comments
 (0)