Attribute Graph (Part 3)
We make sure to recompute nodes in the graph that are marked dirty.
Episode 431 · Nov 29
We make sure to recompute nodes in the graph that are marked dirty.
Episode 431 · Nov 29
We automatically add edges in the attribute graph and invalidate edges and nodes when necessary.
Episode 430 · Nov 22
We start to work on a reimplementation of SwiftUI's attribute graph.
Episode 429 · Nov 15
We abstract all database accesses in a class to avoid switching isolating contexts all the time.
Episode 428 · Nov 08
We add a SQLite persistency layer to the project and, once again, run into several concurrency errors.
Episode 427 · Nov 01
We refactor the code to take a snapshot of the web view into the common SwiftUI reader pattern.
Episode 426 · Oct 25
We add a web view to the project and try two different methods to take a snapshot asynchronously.
Episode 425 · Oct 18
We start a new macOS project to explore Swift 6's concurrency features.
Episode 424 · Oct 11
We turn the specific spray effect into a generic particle system and add a second effect.
Episode 423 · Oct 04
We make sure to garbage collect old particles and to pause and resume the timeline view.
Episode 422 · Sep 27
We combine the canvas-based drawing from last episode with a keyframe timeline to control the particles.
Episode 421 · Sep 20
We improve the performance of the particle effect by rendering the particles in a canvas view.
Episode 420 · Sep 13
We make our particle effect more flexible by combining it with a keyframe timeline.
Episode 419 · Sep 06
We start building a particle effect, using transitions as the first approach.
Episode 418 · Aug 30
We make our lazy vertical stack implementation more generic to support other kinds of vertical layouts.
Episode 417 · Aug 16
We continue to work on our custom lazy stack implementation and add support for preferred spacing.
Episode 416 · Aug 09
We try to re-implement a lazy vertical stack based off last week's experiments.
Episode 415 · Aug 02
We investigate SwiftUI's new group APIs for building custom lazy container views.
Episode 414 · Jul 26
We finish the bento layout by adding spacing and fixing a crash.
Episode 413 · Jul 19
We reimplement our bento layout on top of SwiftUI's layout protocol.
Episode 412 · Jul 05
We use the new Group API to turn our bento view into a custom container.
Episode 411 · Jun 28
We start implementing a bento layout using two different approaches.
Episode 410 · Jun 21
We discuss some subtleties around SwiftUI's view updates with regard to environment and preference changes.
Episode 409 · Jun 14
We automatically position the tooltips depending on the available space around the anchor view.
Episode 408 · Jun 07
We implement a custom tooltip API that only shows one tooltip at a time.
Episode 407 · May 31
We show how to detect which views in a lazy stack are currently onscreen.
Episode 406 · May 24
We use a custom animation to manually control the progress of animations using a slider.
Episode 405 · May 17
We implement the picker animation from the last episode using three more preference-based techniques.
Episode 404 · May 10
We build a picker with an animated underline using alignment and the matched geometry effect.
Episode 403 · May 03
We implement a wobble animation using a phase animator and the Animatable API.
Episode 402 · Apr 19
We use anchors and preferences to position the badges on top of all icons.
Episode 401 · Apr 12
We implement a badge view that scales with the content and position it using alignment.
Episode 400 · Apr 05
We reimplement SwiftUI's default button style to better understand its behavior.
Episode 399 · Mar 29
We add the fill content mode to our conditional aspect ratio layout and make sure it can handle nil proposals.
Episode 398 · Mar 22
We implement a custom version of SwiftUI's aspectRatio modifier that can be enabled or disabled.
Episode 397 · Mar 15
We add the ability to pass annotations, like syntax highlighting information, through the pretty printer.
Episode 396 · Mar 08
We continue to work on our pretty printers to indent a Swift parameter list in various ways.
Episode 395 · Mar 01
We add a choice operator to our pretty printing library to generate the best output for a given column width.
Episode 394 · Feb 23
We begin implementing a pretty printing library based on an old Haskell paper.
Episode 393 · Feb 16
We add a hover effect to the legend view, highlighting the legend labels, as well as the views they point to.
Episode 392 · Feb 09
Building on the previous episode, we improve the horizontal alignment of the legend labels.
Episode 391 · Feb 02
We build a legend view using anchors and preferences.
Episode 390 · Jan 26
We create a pattern image shape style from a SwiftUI view.
Episode 389 · Jan 19
We improve the keys used to distinguish multiple tweakable values and add a tweakable container view.
Episode 388 · Jan 12
We add custom editors for tweakable values, simplifying our code at the same time.
Episode 387 · Jan 05
We make our tweakable helper generic so that we can adjust any type of value.
Episode 386 · Dec 22 2023
We discuss the basic approach to implementing tweakable values in SwiftUI.
Episode 385 · Dec 15 2023
We show some more use cases for structural programming, like generating random values.
Episode 384 · Dec 08 2023
We adapt our existing macros to support the new separation between types and values.
Episode 383 · Dec 01 2023
We restructure our library to separate the structure of types from their values.
Episode 382 · Nov 24 2023
We add support for enums to our structural programming library.
Episode 381 · Nov 17 2023
We use our structural programming library to generate SwiftUI forms for arbitrary structs.
Episode 380 · Nov 10 2023
We use Swift macros to generate the structural representation of structs.
Episode 379 · Nov 03 2023
We introduce a concept called structural programming and take the first steps toward an implementation.
Episode 378 · Oct 27 2023
We try to improve the performance and energy usage of the marquee view — with mixed results.
Episode 377 · Oct 20 2023
We add smooth velocity transitions to our marquee component and clean up the code.
Episode 376 · Oct 13 2023
We change our marquee animation to a tick-based approach and add a drag gesture.
Episode 375 · Oct 06 2023
We start building a marquee component using SwiftUI's timeline view.
Episode 374 · Sep 29 2023
We implement Catmull-Rom splines to interpolate smoothly between multiple cubic keyframes.
Episode 373 · Sep 22 2023
We add automatic smooth transitions between linear and cubic keyframes.
Episode 372 · Sep 15 2023
We implement the start and end velocity parameters for cubic keyframes.
Episode 371 · Sep 08 2023
We integrate our custom Bézier function from last episode to implement cubic keyframes.
Episode 370 · Sep 01 2023
We start implementing cubic keyframes by defining our own Bézier function.
Episode 369 · Aug 25 2023
We use a timeline view to animate views using our own keyframe implementation.
Episode 368 · Aug 18 2023
We implement the keyframe timeline type and add the possibility of having multiple keyframe types.
Episode 367 · Aug 11 2023
We reimplement SwiftUI's new keyframe-based animations, starting with linear keyframes.
Episode 366 · Aug 04 2023
We continue the macro implementation with generating getters and setters for the observed properties.
Episode 365 · Jul 28 2023
We implement a macro to automatically generate the code necessary for observation.
Episode 364 · Jul 21 2023
We make one-time observation calls work by working with observer IDs.
Episode 363 · Jul 14 2023
We begin reimplementing Swift's new observation mechanism by tracking access to observable objects.
Episode 362 · Jul 07 2023
In the last episode of this series, we implement the writing of trees and commits.
Episode 361 · Jun 30 2023
After having parsed blobs, trees, and commits, we now implement writing data, starting with blobs.
Episode 360 · Jun 23 2023
We parse Git commits, including the commit message and multiline metadata.
Episode 359 · Jun 16 2023
We add parsing of trees to our Swift Git implementation.
Episode 358 · Jun 02 2023
We implement Git's data structure in Swift, starting with blobs.
Episode 357 · May 26 2023
We explore multiple ways to draw dotted lines between two points in SwiftUI.
Episode 356 · May 19 2023
We refactor our connecting lines code, disentangling the anchor logic from the content.
Episode 355 · May 12 2023
We use SwiftUI's anchors to draw connecting lines between multiple views in the view hierarchy.
Episode 354 · May 05 2023
We refactor our anchor implementation to support transforms like scaling and rotation.
Episode 353 · Apr 28 2023
We continue the anchor implementation, adding support for point anchors.
Episode 352 · Apr 21 2023
We reimplement SwiftUI's anchors to better understand what they do, starting with the bounds anchor.
Episode 351 · Apr 14 2023
We add support for vertical alignment to our Layout protocol-based Flow layout implementation.
Episode 350 · Apr 07 2023
We implement the decoder for our Codable-based routing system.
Episode 349 · Mar 31 2023
We build a routing system based on the Codable protocol, starting with encoding.
Episode 348 · Mar 24 2023
We implement a rule modifier protocol that's similar to SwiftUI's view modifier protocol.
Episode 347 · Mar 17 2023
We add a simple web server to test our library from the browser and add support for async code.
Episode 346 · Mar 10 2023
We add a user-extensible environment to loop custom values through the site tree.
Episode 345 · Mar 03 2023
We add helpers to construct static and dynamic paths.
Episode 344 · Feb 24 2023
We lay the foundation for a backend library inspired by SwiftUI.
Episode 343 · Feb 17 2023
To conclude this series, we render the result of our attributed string builder to a PDF file.
Episode 342 · Feb 10 2023
We add support for Markdown and make it styleable using a custom stylesheet.
Episode 341 · Feb 03 2023
We add support for images and SwiftUI embeds to our attributed string builder.
Episode 340 · Jan 27 2023
We add modifiers to apply various kinds of attributes and integrate Swift syntax highlighting.
Episode 339 · Jan 20 2023
We refactor the attributed string builder to support joining with a configurable separator.
Episode 338 · Jan 13 2023
We begin implementing an attributed string builder to replace the legacy infrastructure for rendering our books.
Episode 337 · Jan 06 2023
We make sure to restore the scroll position when switching tabs while keeping the picker stationary.
Episode 336 · Dec 23 2022
We use our sticky modifier to implement a tabbed scroll view with a sticky picker.
Episode 335 · Dec 16 2022
We improve our sticky header implementation with a nicer API and a subtle bug fix.
Episode 334 · Dec 09 2022
We implement a sticky modifier that makes views in a scroll stick to the top.
Episode 333 · Dec 02 2022
We use an animatable view to control the staggered animation with one common timing curve.
Episode 332 · Nov 25 2022
We use SwiftUI's semi-private variadic view API to create a better interface for our staggered animations.
Episode 331 · Nov 18 2022
We investigate different ways to create staggered animations, starting with delayed animations.
Episode 330 · Nov 11 2022
We clean up the async image caching code from the last episode to end up with a nicer interface.
Episode 329 · Nov 04 2022
We look at two different ways of improving the caching behavior of our AsyncImage implementation.
Episode 328 · Oct 28 2022
We create two versions of our async image implementation for more control over the data's lifetime.
Episode 327 · Oct 21 2022
We tackle the shape of the notch, make the clock auto update, and add the Home indicator.
Episode 326 · Oct 14 2022
We build a view modifier to make any view look like it’s rendered within an iPhone simulator.
Episode 325 · Oct 07 2022
We work on the accessibility of our custom stepper component.
Episode 324 · Sep 30 2022
We make the custom stepper styleable via the environment and create a hold-to-increment/decrement stepper style.
Episode 323 · Sep 23 2022
We introduce a stepper style protocol that allows us to create a wide range of appearances for our custom stepper.
Episode 322 · Sep 16 2022
We start building a custom stepper component and make it adapt to SwiftUI's control size.
Episode 321 · Sep 09 2022
We’re joined by Kasper to take a look at building custom components, beginning with exploring SwiftUI's built-in component styling.
Episode 320 · Sep 02 2022
We use the layout inspection wrapper from the last episode to examine how HStack's layout works.
Episode 319 · Aug 26 2022
We use SwiftUI's new Layout protocol to inspect the proposed and reported sizes in the layout process.
Episode 318 · Aug 19 2022
On selection of a search result, we jump to the relevant page and highlight the search term.
Episode 317 · Aug 12 2022
We add a search field to our SwiftUI workshop app and prepare the content to be searchable.
Episode 316 · Aug 05 2022
We add a search field to our SwiftUI workshop app and prepare the content to be searchable.
Episode 315 · Jul 29 2022
We clean up the code of the last few episodes by splitting our large view into smaller parts.
Episode 314 · Jul 22 2022
We implement some vector math to calculate the initial animation velocity from the drag gesture.
Episode 313 · Jul 15 2022
We lay the foundation for using a spring animation with the initial velocity for the drag gesture.
Episode 312 · Jul 08 2022
We add a drag gesture to close the detail view when it's being pulled down.
Episode 311 · Jul 01 2022
We add smooth animations from the photo grid to the detail view and back.
Episode 310 · Jun 24 2022
We start to build a photo grid view like in the stock Photos app, including gestures and transitions.
Episode 309 · Jun 17 2022
We take a first look at SwiftUI's new Layout protocol and integrate the flow layout we previously built.
Episode 308 · Jun 10 2022
We build a UI for creating chains of async algorithms and visualizing the results.
Episode 307 · Jun 03 2022
We refactor our code to support combining multiple async algorithms.
Episode 306 · May 27 2022
We add support for more algorithms, like zip and combineLatest, and clean up our code.
Episode 305 · May 20 2022
We add drag gestures to make the input streams interactive.
Episode 304 · May 13 2022
We transform arrays of events into async streams, run the merge algorithm on them, and visualize the result.
Episode 303 · May 06 2022
We start a new project to visualize the algorithms from the new Swift Async Algorithms package.
Episode 302 · Apr 29 2022
We conform our CRDT sequence to multiple collection protocols and use it for syncing a simple to-do app.
Episode 301 · Apr 22 2022
We add the ability to delete elements from our CRDT sequence and test the behavior for correctness.
Episode 300 · Apr 15 2022
We change the backing storage of our CRDT sequence from a tree to an array for efficiency.
Episode 299 · Apr 08 2022
We implement and test the merge algorithm for our tree-backed sequence data type.
Episode 298 · Apr 01 2022
We start building a replicated sequence data type, modeling the sequence as a tree.
Episode 297 · Mar 25 2022
After adding more testing to our CRDTs, we integrate them into a small app.
Episode 296 · Mar 18 2022
We implement our second CRDT, a grow-only counter type, and test its behavior.
Episode 295 · Mar 11 2022
We begin to investigate Conflict-Free Replicated Data Types as a way to sync data across devices.
Episode 294 · Mar 04 2022
We use type-level programming to specify the alignment for each level of the tree diagram separately.
Episode 293 · Feb 25 2022
We use a custom alignment ID to control the positioning of parent nodes in our tree.
Episode 292 · Feb 18 2022
We prepare a tree diagram view in SwiftUI to experiment with advanced alignment techniques.
Episode 291 · Feb 11 2022
We add cancelation to the AsyncStream-based interface of our web crawler.
Episode 290 · Feb 04 2022
We refactor our web crawler to report its results via an AsyncStream instead of an observable object.
Episode 289 · Jan 28 2022
We use Swift's manual continuation APIs to replace a Task.sleep in our web crawler.
Episode 288 · Jan 21 2022
We parallelize the web crawler using a task group and an actor for synchronization.
Episode 287 · Jan 14 2022
We start implementing a concurrent web crawler to experiment with task groups and actors.
Episode 286 · Jan 07 2022
We show how animations in SwiftUI are implemented using transactions.
Episode 285 · Dec 17 2021
We bridge between URLSession's delegate methods and an async version of the delegate protocol.
Episode 284 · Dec 10 2021
We experiment with modeling delegate callbacks as events in an AsyncStream.
Episode 283 · Dec 03 2021
We explore ways to bridge between the old and new concurrency worlds using tasks and continuations.
Episode 282 · Nov 26 2021
We start implementing a download manager as a sample project for exploring Swift's new concurrency model.
Episode 281 · Nov 19 2021
We detect the dates in our graph that are onscreen and use this to control a date picker.
Episode 280 · Nov 12 2021
We refine our graph view and add the ability to programmatically control the scroll view.
Episode 279 · Nov 05 2021
We start building a scrolling graph view that can display large amounts of data smoothly.
Episode 278 · Oct 29 2021
We implement a property wrapper to access values from our environment.
Episode 277 · Oct 22 2021
We add support for loops to our rule builder, and we implement a basic template infrastructure.
Episode 276 · Oct 15 2021
We implement a result builder that enables us to compose rules similar to SwiftUI views.
Episode 275 · Oct 08 2021
We mimic SwiftUI's environment design to pass values down the site rule hierarchy.
Episode 274 · Oct 01 2021
We show how we replaced our outdated Ruby website with a SwiftUI-inspired static site generator.
Episode 273 · Sep 24 2021
We look at the two different ways async streams can be used and how this relates to memory usage.
Episode 272 · Sep 17 2021
We leverage async/await to write synchronous parsing functions for asynchronous streams of data.
Episode 271 · Sep 10 2021
We build two more async sequences: one to flatten sequences of data, and another one to parse XML.
Episode 270 · Sep 03 2021
We dive into Swift's new async APIs and implement async sequences for chunking and decompressing data.
Episode 269 · Aug 27 2021
We fix two issues around state properties and bindings to make view updates more efficient.
Episode 268 · Aug 20 2021
We add dependency tracking to our state property wrapper to automatically invalidate views.
Episode 267 · Aug 13 2021
We take a first stab at the @State property wrapper, which is easy to use, but not so easy to implement.
Episode 266 · Aug 06 2021
We implement the binding property wrapper and add a projected value on the observed object.
Episode 265 · Jul 30 2021
We use some Swift tricks to equate two Any values, and in turn, we use this to avoid unnecessary view updates.
Episode 264 · Jul 23 2021
To construct more complex view hierarchies for our tests, we first build tuple views and view builders.
Episode 263 · Jul 16 2021
We create the property wrapper for observed objects to automatically invalidate views.
Episode 262 · Jul 09 2021
We define the basic view protocols and build a persistent object tree from view values.
Episode 261 · Jul 02 2021
We finish our reimplementation of the matched geometry effect and discuss the discrepancies between SwiftUI's variant and ours.
Episode 260 · Jun 25 2021
We continue to work on our matched geometry implementation, adding the ability to the position as well as the size.
Episode 259 · Jun 18 2021
We look at SwiftUI's new AsyncImage API and reimplement it using async/await.
Episode 258 · Jun 11 2021
We start reimplementing SwiftUI's matched geometry effect to gain a better understanding of how it works.
Episode 257 · Jun 04 2021
We complete the pinch to open and pinch to close transitions from the last episode.
Episode 256 · May 28 2021
We combine magnification gestures with matched geometry effects to create smooth transitions.
Episode 255 · May 21 2021
We look at a technique similar to SwiftUI's ScrollViewReader to access the underlying MKMapView of a SwiftUI map.
Episode 254 · May 14 2021
We revisit our SwiftUI flow layout implementation from 1.5 years ago and write a simpler and more correct version.
Episode 253 · May 07 2021
We change our app to use the SwiftUI app life cycle, make it document based, and add a custom menu.
Episode 252 · Apr 30 2021
We draw grid lines on our canvas and implement point snapping to this grid.
Episode 251 · Apr 23 2021
We implement keyboard commands with modifiers to be able to move points more precisely.
Episode 250 · Apr 16 2021
We add selection and multi-selection to our path drawing tool.
Episode 249 · Apr 09 2021
We generate SwiftUI path code from the drawing in our app.
Episode 248 · Apr 02 2021
We add more gestures, like double-clicks and dragging with modifiers, to allow editing control points.
Episode 247 · Mar 26 2021
We use drag gestures to allow moving existing points and control points around.
Episode 246 · Mar 19 2021
We implement a click and drag gesture to draw curves and quad curves.
Episode 245 · Mar 12 2021
We start building a Mac app to visually construct SwiftUI paths.
Episode 244 · Mar 05 2021
We implement a row of buttons with equal widths and dynamic content based on the available space.
Episode 243 · Feb 26 2021
We implement a horizontal bar chart with labels at both ends of the bars.
Episode 242 · Feb 19 2021
We implement a real-world layout that looks simple but is not so simple in SwiftUI.
Episode 241 · Feb 12 2021
We create a wrapper view to easily test animations with previews.
Episode 240 · Feb 05 2021
We refactor our SwiftUI views to be testable in previews without mocking the model.
Episode 239 · Jan 29 2021
We add support for flexible columns to our grid view implementation.
Episode 238 · Jan 22 2021
For the final SwiftUI view in this series, we examine the layout of grid views with fixed columns.
Episode 237 · Jan 15 2021
We write an automated fuzz test for our HStack implementation and uncover a subtle bug in the process.
Episode 236 · Jan 08 2021
We adjust the HStack layout algorithm to work with child views of different layout priorities.
Episode 235 · Dec 24 2020
We continue adding support for custom alignment to all our views, focusing in particular on HStack.
Episode 234 · Dec 18 2020
We add SwiftUI's custom alignment guide API and make it work with fixed frames.
Episode 233 · Dec 11 2020
We continue with our HStack implementation to make it work with fixed and flexible views.
Episode 232 · Dec 04 2020
We begin the implementation of HStack, starting with support for fixed size children.
Episode 231 · Nov 27 2020
We add SwiftUI's fixed size modifier and explain how it works with text and flexible frames.
Episode 230 · Nov 20 2020
We replicate the behavior of flexible frames with minimum and maximum widths.
Episode 229 · Nov 13 2020
We implement Text, Overlay, and Geometry Reader to measure views and display their sizes onscreen.
Episode 228 · Nov 06 2020
We replicate SwiftUI's alignment types and add the alignment parameter to the fixed frame API.
Episode 227 · Oct 30 2020
We implement fixed frames to understand how the proposed size, frame size, and content size interact.
Episode 226 · Oct 23 2020
We reimplement parts of SwiftUI's layout system — starting with view protocols and shapes — to understand it better.
Episode 225 · Oct 16 2020
We switch to a bottom-up approach to render trees in a compact but symmetric fashion.
Episode 224 · Oct 09 2020
We experiment with different tree-drawing algorithms to produce readable and compact binary trees.
Episode 223 · Oct 02 2020
We provide the current slide number and total slide count via the environment and display them in the footer.
Episode 222 · Sep 25 2020
We add custom animations and use SwiftUI's matched geometry effect for animations between slides.
Episode 221 · Sep 18 2020
We create a wrapper view for slide headers that allows us to style all headers via the environment.
Episode 220 · Sep 11 2020
We scale our slides to fit any screen size and use SwiftUI Previews to render previews of all slides.
Episode 219 · Sep 04 2020
We implement a custom function builder to enable writing slides with the same syntax as SwiftUI views.
Episode 218 · Aug 28 2020
We start building a SwiftUI library for creating presentation slides.
Episode 217 · Aug 21 2020
We execute the fuzzy matching algorithm concurrently to reach 60 frames per second.
Episode 216 · Aug 14 2020
We improve the performance of the fuzzy search algorithm by using better data types and avoiding unnecessary work.
Episode 215 · Aug 07 2020
We lay the foundation for future performance improvements by refactoring our recursive algorithm to a matrix-based one.
Episode 214 · Jul 31 2020
We switch to a recursive algorithm to perform a complete fuzzy match.
Episode 213 · Jul 24 2020
To rank order search results, we introduce scores for matches and gaps.
Episode 212 · Jul 17 2020
We start building a Quick Open feature by implementing a simple fuzzy matching algorithm.
Episode 211 · Jul 10 2020
We conclude this series by fixing some minor bugs and adding member expressions to our template language.
Episode 210 · Jul 03 2020
We implement the evaluation of for loops using tests for success and failure cases.
Episode 209 · Jun 26 2020
We add for loops to our parser, making sure to give good error messages for syntax errors.
Episode 208 · Jun 19 2020
We add parsing for HTML attributes and escape them properly during evaluation.
Episode 207 · Jun 12 2020
We annotate the syntax tree with source positions, which allows us to improve the errors during evaluation.
Episode 206 · Jun 05 2020
We start implementing the evaluation part of our template language.
Episode 205 · May 29 2020
We add proper parse errors with source positions, making it much easier to diagnose problems.
Episode 204 · May 22 2020
We start building an HTML template language, implementing the parser in a test-driven way.
Episode 203 · May 15 2020
We rebuild the model layer with structs instead of classes and use bindings to provide mutable access to the views.
Episode 202 · May 08 2020
We use published properties and property observers to clean up our model code, and we fix some issues on the iPad.
Episode 201 · May 01 2020
We take a callback-based model API and refactor it into an observable object.
Episode 200 · Apr 24 2020
We create a lazy wrapper for observable objects and use dynamic member lookup to ease its use.
Episode 199 · Apr 17 2020
We wrap a UIKit alert in a SwiftUI-like API to present an alert with a text field.
Episode 198 · Apr 10 2020
We continue working on the recording and playback screens while reusing existing model and helper classes from the MVC app.
Episode 197 · Apr 03 2020
We start to implement the MVC sample app from our App Architecture book in SwiftUI reusing the original model.
Episode 196 · Mar 27 2020
We wrap an MKMapView, using a diff on the annotations to properly animate insertions and removals.
Episode 195 · Mar 20 2020
We create a view that automatically scales a text view to fill the available space.
Episode 194 · Mar 13 2020
We add labels to the analog clock face, and we make it configurable to reuse it for counting the minutes.
Episode 193 · Mar 06 2020
We draw an analog clock face and add moving pointers.
Episode 192 · Feb 28 2020
We improve upon the virtual joystick for the 3D perspective, and we add basic lighting and widescreen support.
Episode 191 · Feb 21 2020
We use the ray casting algorithm from the last episode to draw the scene in 3D for the first time.
Episode 190 · Feb 14 2020
We prepare for drawing the scene in 3D by implementing a ray casting algorithm.
Episode 189 · Feb 07 2020
We introduce player direction and implement a line drawing algorithm to visualize it.
Episode 188 · Jan 31 2020
After making some improvements to the virtual joystick, we move on to collision detection and collision response.
Episode 187 · Jan 24 2020
We load the maze, render it onscreen, and add a virtual joystick to control player movement.
Episode 186 · Jan 17 2020
We add rudimentary play physics and decouple the world and bitmap dimensions to create smooth motion.
Episode 185 · Jan 10 2020
Special guest Nick Lockwood guides us through his first tutorial for recreating a retro game using techniques from the 90s.
Episode 184 · Jan 03 2020
We add lap times to the model, show them in a list, and highlight the shortest and longest laps.
Episode 183 · Dec 20 2019
We add the data model for the stopwatch to make it functional.
Episode 182 · Dec 13 2019
We enable our stopwatch buttons to self-size to fit their labels.
Episode 181 · Dec 06 2019
We use a custom button style to imitate the appearance of the stopwatch buttons on iOS.
Episode 180 · Nov 29 2019
We refactor our use of geometry readers and preferences to make our code more expressive.
Episode 179 · Nov 22 2019
We implement the drop functionality and work around several obstacles we encounter along the way.
Episode 178 · Nov 15 2019
We make our shopping cart interactive by adding drag and drop.
Episode 177 · Nov 08 2019
We use a view modifier with local state to animate views onto the screen.
Episode 176 · Nov 01 2019
We use anchors, preferences, and transitions to animate items from a grid into a cart.
Episode 175 · Oct 25 2019
We examine SwiftUI's animation curves using a custom view modifier.
Episode 174 · Oct 18 2019
We explore SwiftUI's rendering and animation model while building a shake animation.
Episode 173 · Oct 11 2019
We combine the logic for parsing 64-byte chunks from the last episode to process entire files.
Episode 172 · Oct 04 2019
We experiment with porting the low-level approach of a super-fast JSON parsing library to Swift.
Episode 171 · Sep 27 2019
We show a parsing technique that we use for many parsing tasks in our day-to-day work.
Episode 170 · Sep 20 2019
We use drag gesture recognizers to add reordering capabilities to our SwiftUI collection view.
Episode 169 · Sep 13 2019
We implement single-line and flow layouts for our SwiftUI collection view.
Episode 168 · Sep 06 2019
As a first step toward a collection view, we enable child views to communicate their sizes to a parent view.
Episode 167 · Aug 30 2019
We further refine the animation from last episode and refactor it using a geometry effect.
Episode 166 · Aug 23 2019
We start building a custom animation of a shape that moves along a path.
Episode 165 · Aug 16 2019
We experiment with paths and shapes to create a triangular preview badge.
Episode 164 · Aug 09 2019
We integrate Apple's web authentication framework to enable logging in with GitHub and then store the credentials using a keychain property wrapper.
Episode 163 · Aug 02 2019
We create a two-way binding from the play position of the video player to a bindable model object.
Episode 162 · Jul 26 2019
We integrate an AVPlayerViewController, expose its play state as a binding, and use a SwiftUI view as an overlay.
Episode 161 · Jul 17 2019
We look at different ways to load data from the network less eagerly.
Episode 160 · Jul 12 2019
We explore different approaches to passing data around in our SwiftUI app.
Episode 159 · Jul 05 2019
We start building a Swift Talk app using SwiftUI.
Episode 158 · Jun 28 2019
We integrate the tiny networking library into a SwiftUI project and wrap AppKit's progress indicator in a SwiftUI view.
Episode 157 · Jun 21 2019
We build a simple currency converter to experiment with SwiftUI's state-driven view updates.
Episode 156 · Jun 14 2019
We improve the performance of syntax highlighting to be able to work in large documents.
Episode 155 · Jun 07 2019
We use several pieces of code from earlier episodes to build a link checking extension on URLSession.
Episode 154 · May 31 2019
We discuss how Swift's type system can be used to eliminate impossible states from our code.
Episode 153 · May 24 2019
We implement fold on the CommonMark syntax tree and use it to extract links and text from a document.
Episode 152 · May 17 2019
We explore the differences between reduce and fold and how they can be implemented on any enum.
Episode 151 · May 10 2019
Wouter joins us to explore the origins of the reduce function.
Episode 150 · May 03 2019
We use SwiftSyntax to add highlighting for Swift code blocks.
Episode 149 · Apr 26 2019
We fix a couple of string-related bugs when interoperating with the cmark library and the REPL.
Episode 148 · Apr 19 2019
We launch a Swift REPL process to execute Swift code in our Markdown file.
Episode 147 · Apr 12 2019
We use CommonMark to parse the markdown string and then add attributes to highlight its syntax.
Episode 146 · Apr 05 2019
We start building our Markdown Playgrounds app from a plain command-line app package, leveraging AppKit's document architecture.
Episode 145 · Mar 29 2019
We refactor our string interpolation code to allow concatenation of multiple interpolated SQL queries.
Episode 144 · Mar 22 2019
We use Swift 5's new string interpolation API to automatically insert placeholders in SQL queries.
Episode 143 · Mar 15 2019
Using a protocol-based approach, we show how we write tests for the Swift Talk backend.
Episode 142 · Mar 08 2019
We show a refactoring of the view code in the Swift Talk backend that allows us to pass around dependencies automatically using a functional pattern.
Episode 141 · Mar 01 2019
To finish up the team member signup, we use a CSRF-validated POST request and then write a test for what we've built.
Episode 140 · Feb 22 2019
We continue working on the team member signup feature, showing how we handle sessions and perform database queries.
Episode 139 · Feb 15 2019
We show our new Swift Talk backend built on top of SwiftNIO by implementing a new team member signup feature.
Episode 138 · Feb 08 2019
We implement a test URL session that we can use to fake network responses.
Episode 137 · Feb 01 2019
We show an alternative implementation of combined resources that uses futures.
Episode 136 · Jan 25 2019
We add zip to the combined resource type, allowing us to express resources with multiple requests in parallel.
Episode 135 · Jan 18 2019
We implement an abstraction on top of our tiny networking library to express resources consisting of multiple requests.
Episode 134 · Jan 11 2019
We revisit the networking library we built in the first episode and discuss improvements we've made over the years.
Episode 133 · Jan 04 2019
We implement Dijkstra's algorithm to find the shortest path between any two points in the trail network.
Episode 132 · Dec 21 2018
We work on the efficiency of our graph-building algorithm, improving it by more than an order of magnitude.
Episode 131 · Dec 14 2018
We improve the graph-building algorithm by detecting overlaps between the tracks.
Episode 130 · Dec 07 2018
We start implementing the algorithm that transforms the GPS points into a graph, which we then visualize for debugging purposes.
Episode 129 · Nov 30 2018
We start implementing the routing logic by looking at the problem of calculating the shortest distance from a point to a line.
Episode 128 · Nov 23 2018
We enable the selection of points on our running tracks by tapping on the map, and we finish up by factoring a lot of this code out of the view controller.
Episode 127 · Nov 16 2018
We show the routing app we'll build in this series and take the first steps by rendering track polygons on a map.
Episode 126 · Nov 09 2018
We show how the layout library we've built over the past two months can be used to adapt to any font and screen size.
Episode 125 · Nov 02 2018
We implement the flexible width option for nested layouts.
Episode 124 · Oct 26 2018
We build upon the nested layout feature from last time to support layout margins, backgrounds, and more.
Episode 123 · Oct 19 2018
We build a feature that allows us to create more complex layouts by nesting layouts within each other.
Episode 122 · Oct 12 2018
We add flexible spaces to our layout library and show how elements can be shown or hidden depending on the available space.
Episode 121 · Oct 05 2018
We refactor our code to remove duplication, improve efficiency, and enable features like flexible spacing.
Episode 120 · Sep 28 2018
We add some features to our layout library — starting with horizontal and vertical spacing — along with a better syntax to define layouts.
Episode 119 · Sep 21 2018
We start building a responsive layout library that makes it easy to create layouts for all screen and font sizes.
Episode 118 · Sep 14 2018
Using a simple key path API, we add the ability to control the visibility of sections by any condition.
Episode 117 · Sep 07 2018
We add support for arrays by implementing an unkeyed decoding container and use custom decoding logic for dates and URLs.
Episode 116 · Aug 31 2018
We implement a custom XML decoder that allows us to decode responses from an XML API using Decodable.
Episode 115 · Aug 24 2018
We're using Swift's Mirror and Decodable APIs to generate database queries for structs in our Swift Talk backend project.
Episode 114 · Aug 17 2018
We return to the form library project and add several features to simplify common tasks.
Episode 113 · Aug 10 2018
We use Apple's new Network framework to simplify our own code.
Episode 112 · Aug 03 2018
We implement a JSON over TCP decoder to enable the debug client to receive data from the Mac app.
Episode 111 · Jul 27 2018
We create a class that encapsulates the complexities of sending data via an output stream.
Episode 110 · Jul 20 2018
We're building a remote view state debugger, starting with the networking code on the client.
Episode 109 · Jul 13 2018
In the last episode of this series, we factor out view code from the large view controller into a custom view class.
Episode 108 · Jul 06 2018
We use the child view controller we created last time to factor out more code from the large view controller.
Episode 107 · Jun 29 2018
We extract a child view controller to further slim down our large view controller, making sure the code keeps compiling throughout the process.
Episode 106 · Jun 22 2018
We refactor networking-related code out of the view controller, separating networking and data transformation logic from UI code in the process.
Episode 105 · Jun 15 2018
We extract Core Data-related code from the large view controller and move it into the model layer.
Episode 104 · Jun 08 2018
We begin refactoring a large view controller from the Wikipedia iOS app by pulling pieces of helper code out as pure functions.
Episode 103 · Jun 01 2018
After finishing the cleanup from the last episode, we refactor our forms API to be even more succinct and declarative.
Episode 102 · May 25 2018
We create helper functions for form cells and sections, which simplify managing references and propagating updates.
Episode 101 · May 18 2018
In our 100th episode we take questions from our viewers!
Episode 100 · May 12 2018
We extract reusable toggle switch and text field components from our forms code and do more cleaning up in the process.
Episode 99 · May 04 2018
After refactoring in past episodes, it's time for some housekeeping: we clean up our form code and make it more reusable with generics.
Episode 98 · Apr 27 2018
We refactor the form driver class to be reusable and define the entire form in a simple function.
Episode 97 · Apr 20 2018
We continue refactoring our forms code by creating a form table view controller as the first reusable component.
Episode 96 · Apr 13 2018
We begin to refactor the imperative table view code from the last episode, working toward a more declarative approach of defining our form.
Episode 95 · Apr 06 2018
This episode marks the beginning of a new series where we refactor a hand-coded settings form into a reusable, declarative form library. In this episode, we build the base version and discuss the design goals of the library.
Episode 94 · Mar 30 2018
We discuss many considerations and techniques for working with optionals.
Episode 93 · Mar 23 2018
We use Swift's pointer APIs to read a text file and split it into lines without using Swift's collection and string types.
Episode 92 · Mar 16 2018
We extend a basic Markdown library using protocol composition to add support for syntax highlighting in Swift code blocks.
Episode 91 · Mar 09 2018
We implement a concurrent version of the map method for arrays.
Episode 90 · Mar 02 2018
We show how protocol composition can be used to design extensible libraries, thereby solving the so-called "Expression Problem."
Episode 89 · Feb 23 2018
We discuss the capabilities and limitations of enums and classes when designing extensible libraries.
Episode 88 · Feb 16 2018
We continue implementing a mini player in the MVC variant of the sample app found in our App Architecture book.
Episode 87 · Feb 09 2018
We add a mini player to the MVC variant of the sample app found in our App Architecture book. We adjust our storyboard and discuss how to adapt the architecture.
Episode 86 · Feb 02 2018
We write a wrapper around the libgit2 C library to work with Git repositories from macOS and iOS apps — and for the fun of using Swift's pointer APIs!
Episode 85 · Jan 26 2018
Today we're releasing the early access edition of our new App Architecture book. We explain how it came about, what's in it, and how early access works.
Episode 84 · Jan 19 2018
We look at different techniques for wrapping analytics APIs in Swift and discuss their advantages and disadvantages.
Episode 83 · Jan 12 2018
We refactor a simple flow layout to have a functional interface, disentangling the layout code from UIKit code.
Episode 82 · Jan 05 2018
We use Xcode's memory debugger to resolve all the reference cycles in our glitch-free reactive code and introduce a proper ownership model.
Episode 81 · Dec 22 2017
We look at how to work with ranges in a mixed Swift String/NSString environment.
Episode 80 · Dec 15 2017
We benchmark the CSV parsing code from the previous episode and refactor it to become an order of magnitude faster.
Episode 79 · Dec 08 2017
We write a simple CSV parser as an example demonstrating how to work with Swift's String and Substring types.
Episode 78 · Dec 01 2017
We refactor the simple reactive library from the last episode using topological sorting to avoid any temporarily wrong values.
Episode 77 · Nov 24 2017
We look at an example of a reactive pipeline with surprising behavior, discuss why it occurs, and how it could be improved.
Episode 76 · Nov 17 2017
We clean up our layout code by introducing helper functions that leverage Swift's key paths.
Episode 75 · Nov 10 2017
We continue to expand our experimental view binding mechanism to implement dark mode in our app.
Episode 74 · Nov 03 2017
We experiment with reactive view bindings that don't rely on runtime programming.
Episode 73 · Oct 27 2017
We introduce a project we're going to work on over a few episodes. To get familiar with the code, we build a new feature using the app's view-state driven approach.
Episode 72 · Oct 20 2017
Brandon Kase joins us to show how Swift's type system can be leveraged to check file paths at compile time.
Episode 71 · Oct 13 2017
We use the reactive array type from episodes #67 and #69 to back a table view. This allows us to correctly animate changes in the underlying data, even with filter and sort transformations applied.
Episode 70 · Oct 06 2017
We build a reactive array type on top of the reactive list from episode #67 and implement a filter method.
Episode 69 · Sep 29 2017
We extend our Elm-style app with a more dynamic view hierarchy by adding a navigation controller and a table view.
Episode 68 · Sep 22 2017
We build a reactive linked list on top of reactive programming primitives. We implement a reduce method on this type, which does the minimum amount of work when the underlying data changes.
Episode 67 · Sep 15 2017
We refactor our reducer-based project from episode #62 to use The Elm Architecture. Instead of interacting with UIKit directly, we build a virtual view hierarchy and let our Elm framework do the rest.
Episode 66 · Sep 08 2017
We create a custom Quick Look extension to visualize binary tree structures in playgrounds.
Episode 65 · Sep 01 2017
We build a component similar to NSFetchedResultsController to decouple our view data and to drive table view animations.
Episode 64 · Aug 25 2017
We refine the observation capabilities of our new data type.
Episode 63 · Aug 18 2017
We show the reducer pattern to simplify state management and to make typical view controller code more testable.
Episode 62 · Aug 11 2017
We recap the tradeoffs between classes and structs and start implementation of our new type, leveraging Swift 4's keypaths.
Episode 61 · Aug 04 2017
We show some of our favorite new productivity features in Xcode 9.
Episode 60 · Jul 28 2017
We take a look at features like renaming, extracting expressions, extracting methods, and more.
Episode 59 · Jul 21 2017
Building on the binary search tree code from episode #56, we implement red-black trees as self-balancing tree data structures and benchmark their performance.
Episode 58 · Jul 14 2017
Today we're joined by Rob Napier, who explains why and how to add certificate pinning to your app.
Episode 57 · Jul 07 2017
We look at binary search trees as an alternative to last episode's sorted array implementation. We benchmark the performance of insertion and lookup in both data structures, with some surprising results.
Episode 56 · Jun 30 2017
Together with Károly, we improve our sorted array implementation using binary search. We benchmark both implementations to learn about their real-world performance.
Episode 55 · Jun 23 2017
We write a dedicated target-action to make it easier to augment existing UI controls with callbacks.
Episode 54 · Jun 16 2017
Lisa from Kickstarter shows us their test-driven development process to reactive programming.
Episode 53 · Jun 09 2017
Swift 4's new features lets us delete code we've written in previous episodes.
Episode 52 · Jun 02 2017
Brandon from Kickstarter demos how the company uses playgrounds to prototype and style individual view controllers.
Episode 51 · May 26 2017
We extend our libpq wrapper to handle queries with properly escaped parameters. To achieve this, we have to dive deep into Swift's unsafe pointer APIs.
Episode 50 · May 19 2017
Brandon from Kickstarter shows their approach of unifying all potential entry points into an iOS app using a common route enum, both in a simple demo implementaion and in their open source code base.
Episode 49 · May 12 2017
We implement a lightweight wrapper around the libpq C library.
Episode 48 · May 05 2017
Brandon from Kickstarter shows us how they write highly testable code with view models. We integrate Apple Pay payments and look at their open-source codebase.
Episode 47 · Apr 28 2017
We look at multiple ways to create variables that have a class type but also conform to a protocol.
Episode 46 · Apr 21 2017
We implement a type safe and Swift-like routing infrastructure that's pretty different from the common approach of most web frameworks.
Episode 45 · Apr 14 2017
We set up our development environment using the Swift package manager and Docker.
Episode 44 · Apr 07 2017
Instead of letting multiple view controllers manage the navigation bar's state individually, we pull this code out and unify the logic in one place.
Episode 43 · Mar 31 2017
We make our Signal implementation thread-safe by safeguarding the access to shared resources.
Episode 42 · Mar 24 2017
To conform IndexSet to the Collection protocol we implement a custom index type along the way.
Episode 41 · Mar 17 2017
We add the ability to map over signals and control subscriptions in a more fine-grained manner. Along the way, we improve the signal ownership model and implement the concept of disposables.
Episode 40 · Mar 10 2017
We extend the Future type of a previous episode to a simple reactive library. Along the way, we dive into debugging a reference cycle in our implementation.
Episode 39 · Mar 03 2017
Conforming to the Sequence protocol allows us to efficiently iterate over the elements, and we gain all of its useful functionality.
Episode 38 · Feb 24 2017
We build the basics for a custom index set collection type.
Episode 37 · Feb 17 2017
We implement a Futures type that we can use instead of callbacks as a first step towards a reactive library.
Episode 36 · Feb 10 2017
We build a sorted array type on top of Swift's native array and make it conform to the Collection protocol.
Episode 35 · Feb 03 2017
We take a look at how reactive programming challenges us to think differently.
Episode 34 · Jan 27 2017
We make our collection extension even more generic by implementing it on the Sequence protocol.
Episode 33 · Jan 20 2017
We show how to use the Collection protocol to make an extension available not just on array, but on all collections.
Episode 32 · Jan 13 2017
Mutating a nested untyped dictionary can be a challenge. To solve it we discuss the mutability of value types and the concept of l-values.
Episode 31 · Jan 06 2017
We talk about the importance of types and interfaces as tools to express your intent precisely and to set the proper boundaries.
Episode 30 · Dec 30 2016
We refactor a class hierarchy using a protocol and discuss the differences between both approaches.
Episode 29 · Dec 16 2016
We extend our notification wrapper from episode #27 and discuss an alternative protocol-based approach.
Episode 28 · Dec 09 2016
A lightweight generic wrapper around Foundation's notification API lets us avoid boilerplate code and provides a type-safe API.
Episode 27 · Dec 02 2016
We build a generic, type-safe table view controller that can handle multiple cell classes.
Episode 26 · Nov 25 2016
We add support for caching network requests without altering our original networking abstraction.
Episode 25 · Nov 18 2016
We discuss the pros and cons of delegates versus callback functions and why delegate protocols are always class only.
Episode 24 · Nov 11 2016
We talk about a familiar but surprisingly tricky problem: splitting an array into groups of elements. We discuss the pros and cons of our own solutions along with the solutions people sent us via Twitter!
Episode 23 · Nov 04 2016
We show how we build simple command line tools leveraging the Cocoa frameworks. We use the Swift Package manager to include dependencies in our project.
Episode 22 · Oct 28 2016
We can change structs by mutation, functional chaining, and inout parameters. We discuss how they differ at the call site and why they’re all equivalent.
Episode 21 · Oct 21 2016
We use copy-on-write to write an efficient struct wrapper around NSMutableData and discuss how the standard library uses the same approach.
Episode 20 · Oct 14 2016
We build a flexible sort descriptor abstraction on top of Swift's native sort methods, which is dynamic and type safe.
Episode 19 · Oct 07 2016
We leverage the existing infrastructure of our app to add a search field with very little code.
Episode 18 · Sep 30 2016
We connect multiple view controllers using a coordinator and callback functions. We simplify the control flow by refactoring the UI state into its own struct.
Episode 17 · Sep 23 2016
We implement some of the more challenging parts of parser combinators.
Episode 16 · Sep 16 2016
Join us in the functional programming gym to stretch your object-oriented comfort zone while we lay the groundwork for a parser combinator library.
Episode 15 · Sep 09 2016
We build a tree structure from an array of Ledger account names. We first implement the tree using a class, and then we refactor it to a struct and discuss the differences and tradeoffs involved.
Episode 14 · Sep 02 2016
We look at two different techniques to parse a simple expression language: handwritten parsers and parser combinators.
Episode 13 · Aug 26 2016
Writing the code for evaluating transactions required continuous refactoring to keep our code simple and clean.
Episode 12 · Aug 19 2016
Expressions are at the heart of Ledger. We write an evaluator for this expression language in a test-driven way.
Episode 11 · Aug 12 2016
We give a quick introduction to Ledger itself and to the Mac app we're going to build.
Episode 10 · Aug 12 2016
In this episode, we answer some of the questions we've received over the past few weeks. We cover networking, table views, stack views, our App class, and testing.
Episode 9 · Aug 05 2016
We add POST support to a simple networking layer, using Swift's enums with associated values and generics.
Episode 8 · Jul 29 2016
We create an abstraction around stack views using enums to specify UI elements in a declarative style.
Episode 7 · Jul 22 2016
We leverage Swift's generics to keep our table view controller code clean.
Episode 6 · Jul 15 2016
We refactor our code by moving the app's flow from the storyboard into a separate coordinator class. This avoids view controllers having implicit knowledge of their context.
Episode 5 · Jul 08 2016
We add customizable styles to our CommonMark renderer from episode #2.
Episode 4 · Jul 01 2016
We explore different approaches to factor out asynchronous loading code from view controllers, using protocols, container view controllers, and generics.
Episode 3 · Jun 24 2016
We create attributed strings from CommonMark. We continually refactor our code to make the central logic short and understandable.
Episode 2 · Jun 17 2016
We make use of Swift's generics and structs to build a simple network layer with great testability.
Episode 1 · Jun 17 2016