WWDC21 Challenge: Framework Freestyle
At a glance
| Item | Summary |
|---|---|
| Purpose | An AR experience that randomly selects a programming framework and maps it onto the user’s face. |
| App architecture | AppDelegate installs ViewController, which directly owns the ARView, entity setup, audio, and recording/game actions; the small UIKit sample has no separate application-state layer. |
| Main patterns | UIKit lifecycle composition, UI–RealityKit bridge, Delegate callback adapter, Direct ARView composition |
| Project style | Code-light sample with 3 scanned Swift file(s) and 252 implementation line(s). |
Project structure
Source bundle/
└── FrameworkFreestyle-Challenge/
├── ViewController.swift # ViewController
├── AppDelegate.swift # AppDelegate
└── Array+Random.swift
Structure observations
- The runtime boundary is UIApplicationDelegate + UIViewController; the tree is pruned to lifecycle, state, framework, rendering, and ECS files.
- The source is Swift; its compact size does not erase any explicit owner shown below.
Overall architecture
flowchart LR
AppDelegate_1["AppDelegate"]
UIApplicationDelegate___UIViewController_2["UIApplicationDelegate + UIViewController"]
ViewController_3["ViewController"]
RealityKit_entity_graph_4["RealityKit entity graph"]
ARView_scene_5["ARView scene"]
AppDelegate_1 --> UIApplicationDelegate___UIViewController_2
UIApplicationDelegate___UIViewController_2 --> ViewController_3
ViewController_3 --> RealityKit_entity_graph_4
RealityKit_entity_graph_4 --> ARView_scene_5
Reference code
FrameworkFreestyle-Challenge/AppDelegate.swift:10 — executable or app-lifecycle anchor.
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
}The diagram is a responsibility flow, not a claim that every adjacent node directly calls the next. It separates lifecycle, presentation, stable state, framework/session work, and the RealityKit entity graph.
Ownership and state
classDiagram
ViewController --> Face : faceAnchor
ViewController --> ARView : arView
ViewController o-- UIButton : button
ViewController --> RPScreenRecorder : recorder
Ownership evidence
FrameworkFreestyle-Challenge/ViewController.swift:28 — representative stored state or nearest verified lifecycle anchor.
var faceAnchor: Experience.Face?
// MARK: - Constants -
/// The number of times the timer gets called before displaying image. This adds a delay for the
/// question mark to spin before the frameworks start displaying.
let maxTimerCount: Int = 45| Owner | Object or state | Relationship | Mutation authority |
|---|---|---|---|
ViewController |
Face as faceAnchor |
stores and coordinates | The owning type coordinates writes |
ViewController |
ARView as arView |
stores and coordinates | The owning type coordinates writes |
ViewController |
UIButton as button |
receives a shared or non-owning reference | The upstream owner controls lifetime; this scope may invoke the exposed mutable API |
ViewController |
RPScreenRecorder as recorder |
stores and coordinates | The owning type coordinates writes |
Ownership is intentionally narrow: environment, bindings, observed objects, weak links, and delegate callbacks do not prove lifetime ownership. Initialized stored services and wrapper-managed state do; entities added inside a RealityKit content closure belong to that entity graph.
Class and protocol design
| Type | Responsibility | Depends on or conforms to |
|---|---|---|
AppDelegate (FrameworkFreestyle-Challenge/AppDelegate.swift:10) |
Declares app lifecycle and top-level dependency lifetime. | UIResponder, UIApplicationDelegate |
ViewController (FrameworkFreestyle-Challenge/ViewController.swift:15) |
Coordinates long-lived framework or cross-view work. | UIViewController, RPPreviewViewControllerDelegate |
The reviewed source defines no local substitution protocol. Its App, View, delegate, renderer, ARKit, and RealityKit conformances are framework-facing contracts, so this document does not label the whole app protocol-oriented.
Access control
| Symbol | Access | Verified effect | Likely rationale |
|---|---|---|---|
private func startRecording() { (FrameworkFreestyle-Challenge/ViewController.swift:110) |
private |
Use stays inside the declaration and same-file extensions permitted by Swift. | Inference: Hide lifecycle-sensitive state or an implementation step. |
No reviewed Swift access example uses fileprivate, private(set), public, open; declarations without a modifier are internal.
Reference code
FrameworkFreestyle-Challenge/ViewController.swift:110 — representative visibility boundary.
private func startRecording() {
// ...
}Logic ownership and placement
| Logic | Owning type or file | Placement rationale |
|---|---|---|
| Application/command lifecycle | AppDelegate |
The executable boundary determines app, controller, scene, or command lifetime. |
| Presentation and user intent | ViewController |
The view/controller forwards input and owns only presentation-local work. |
Design patterns
| Pattern | Source evidence | Purpose or tradeoff |
|---|---|---|
| UIKit lifecycle composition | FrameworkFreestyle-Challenge/AppDelegate.swift:10 |
Uses the application delegate and view controller as the explicit lifecycle and scene-ownership boundary. |
| UI–RealityKit bridge | FrameworkFreestyle-Challenge/ViewController.swift:15 |
Builds or hosts the RealityKit entity graph from SwiftUI or a platform view/controller lifecycle. |
| Delegate callback adapter | FrameworkFreestyle-Challenge/AppDelegate.swift:10 |
Inverts imperative framework callbacks into the sample’s owning controller, coordinator, or model. |
| Direct ARView composition | FrameworkFreestyle-Challenge/ViewController.swift:18 |
Keeps the challenge-sized experience in one controller; the tradeoff is intentionally limited substitution and test seams. |
Naming conventions
- Role suffixes are evidence, not decoration: Controller:
ViewController. - Protocols: no app-defined protocol in the reviewed source.
- Commands use verb-led methods:
viewDidLoad,viewDidAppear,setupMaterials,toggleRecording,startRecording,stopRecording,handleImageAnimationsSequence,createUnlitMaterialWithTexture. - Files and folders use primary-type or responsibility names such as
Views,Models,Rendering,Components,Systems,Packages, or feature names where those boundaries exist.
Architecture takeaways
- Treat
AppDelegateas the owner of executable or scene lifecycle, not automatically as the owner of every entity created later. - Keep view/controller input near presentation, but move sessions, reconstruction, capture, rendering, shared game state, or documents into stable owners when their lifetime exceeds one callback or render pass.
- The compact source does not justify repository, coordinator, or protocol layers beyond boundaries the sample actually declares.
Source map
| Source file | Relevant symbols |
|---|---|
FrameworkFreestyle-Challenge/ViewController.swift:15 |
ViewController |
FrameworkFreestyle-Challenge/AppDelegate.swift:10 |
AppDelegate |
FrameworkFreestyle-Challenge/Array+Random.swift:1 |
Feature implementation |