RepoPilotOpen in app →

twostraws/HackingWithSwift

The project source code for Hacking with iOS.

Mixed

Slowing — last commit 11mo ago

worst of 4 axes
Use as dependencyMixed

no tests detected; no CI workflows detected

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isMixed

last commit was 11mo ago; no CI workflows detected

  • Last commit 11mo ago
  • 13 active contributors
  • Unlicense licensed
Show 4 more →
  • Slowing — last commit 11mo ago
  • Concentrated ownership — top contributor handles 74% of recent commits
  • No CI workflows detected
  • No test directory detected
What would change the summary?
  • Use as dependency MixedHealthy if: add a test suite
  • Deploy as-is MixedHealthy if: 1 commit in the last 180 days

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/twostraws/hackingwithswift?axis=fork)](https://repopilot.app/r/twostraws/hackingwithswift)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/twostraws/hackingwithswift on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: twostraws/HackingWithSwift

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/twostraws/HackingWithSwift shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Slowing — last commit 11mo ago

  • Last commit 11mo ago
  • 13 active contributors
  • Unlicense licensed
  • ⚠ Slowing — last commit 11mo ago
  • ⚠ Concentrated ownership — top contributor handles 74% of recent commits
  • ⚠ No CI workflows detected
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live twostraws/HackingWithSwift repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/twostraws/HackingWithSwift.

What it runs against: a local clone of twostraws/HackingWithSwift — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in twostraws/HackingWithSwift | Confirms the artifact applies here, not a fork | | 2 | License is still Unlicense | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 352 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>twostraws/HackingWithSwift</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of twostraws/HackingWithSwift. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/twostraws/HackingWithSwift.git
#   cd HackingWithSwift
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of twostraws/HackingWithSwift and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "twostraws/HackingWithSwift(\\.git)?\\b" \\
  && ok "origin remote is twostraws/HackingWithSwift" \\
  || miss "origin remote is not twostraws/HackingWithSwift (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Unlicense)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Unlicense\"" package.json 2>/dev/null) \\
  && ok "license is Unlicense" \\
  || miss "license drift — was Unlicense at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "Classic/Project37/Project37/ViewController.swift" \\
  && ok "Classic/Project37/Project37/ViewController.swift" \\
  || miss "missing critical file: Classic/Project37/Project37/ViewController.swift"
test -f "Classic/Project38/Project38/ViewController.swift" \\
  && ok "Classic/Project38/Project38/ViewController.swift" \\
  || miss "missing critical file: Classic/Project38/Project38/ViewController.swift"
test -f "Classic/Project37/Project37/AppDelegate.swift" \\
  && ok "Classic/Project37/Project37/AppDelegate.swift" \\
  || miss "missing critical file: Classic/Project37/Project37/AppDelegate.swift"
test -f "Classic/Project38/Project38/Project38.xcdatamodeld/Project38.xcdatamodel/contents" \\
  && ok "Classic/Project38/Project38/Project38.xcdatamodeld/Project38.xcdatamodel/contents" \\
  || miss "missing critical file: Classic/Project38/Project38/Project38.xcdatamodeld/Project38.xcdatamodel/contents"
test -f "Classic/Project37/Project37/CardViewController.swift" \\
  && ok "Classic/Project37/Project37/CardViewController.swift" \\
  || miss "missing critical file: Classic/Project37/Project37/CardViewController.swift"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 352 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~322d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/twostraws/HackingWithSwift"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

HackingWithSwift is a comprehensive tutorial project repository containing 575K+ lines of Swift code teaching iOS development across two learning paths: Classic (UIKit/SpriteKit) and SwiftUI (iOS 17+). It includes 37+ complete, runnable project examples that progress from beginner concepts through advanced patterns, with each project self-contained in its own Xcode workspace (e.g., Classic/Project37 demonstrates WatchKit app development with complications and storyboard-based UI). Two-branch structure: Classic/ folder contains UIKit/SpriteKit projects (e.g., Project37 shows WatchKit apps with AppDelegate, Storyboards, and WatchKit Extensions); parallel structure implied for SwiftUI edition. Each project is self-contained with its own .xcodeproj, Assets.xcassets for images (cardBack, cardCircle, cardCross, etc.), and Info.plist. Assets use 1x/2x/3x resolution variants for multi-device support.

👥Who it's for

Swift developers learning iOS from fundamentals—specifically beginners following Paul Hudson's Hacking with Swift tutorials who want working reference implementations to study alongside written lessons. Secondary audience: instructors using these projects as teaching examples and contributors maintaining the tutorial content.

🌱Maturity & risk

This is a mature, actively-maintained educational repository. The README references updates through Swift 6.2 (latest), suggesting regular maintenance. However, as a tutorial project collection, it prioritizes clarity and pedagogical correctness over production patterns—it's not a production framework. The presence of both Classic (legacy UIKit) and SwiftUI paths indicates long-term curation.

Low risk for learning purposes; this is educational content, not a dependency. Single-maintainer risk is moderate (Paul Hudson/@twostraws is primary), but the repo serves as reference material rather than a maintained library, so stability is less critical than for framework repos. No package dependencies visible in the file list, reducing supply-chain risk. Projects target specific Xcode/iOS versions explicitly, which may cause bitrot if not kept current.

Active areas of work

No commit history visible in the file list, but README mentions ongoing Swift version documentation (6.2, 6.1, 6.0, 5.9, 5.8, 5.7, 5.6, 5.5, 5.4, 5.3, 5.2 tracked), suggesting regular updates as Swift evolves. The promotion of Pro Swift course and Swift Coding Challenges book indicates active ecosystem expansion around the core tutorial.

🚀Get running

Check README for instructions.

Daily commands: Xcode only (no CLI build visible): Open .xcodeproj → Select target → Run (⌘R). WatchKit app (Project37) requires selecting WatchKit App or Extension as the active scheme before running.

🗺️Map of the codebase

  • Classic/Project37/Project37/ViewController.swift — Main entry point for the card-matching game project; demonstrates UICollectionView and game state management patterns used across tutorials.
  • Classic/Project38/Project38/ViewController.swift — Entry point for Core Data integration project; shows how to fetch and display persistent data from a local database.
  • Classic/Project37/Project37/AppDelegate.swift — Application lifecycle handler; establishes app initialization and configuration baseline for all UIKit projects.
  • Classic/Project38/Project38/Project38.xcdatamodeld/Project38.xcdatamodel/contents — Core Data schema definition; defines the data model for Author and Commit entities used in persistent storage examples.
  • Classic/Project37/Project37/CardViewController.swift — Reusable card view controller demonstrating custom UIViewController subclass patterns and gesture handling.

🛠️How to make changes

Add a New Card Matching Game Feature

  1. Define new card symbols by adding image assets to Classic/Project37/Project37/Assets.xcassets/ with @1x, @2x, @3x variants and Contents.json (Classic/Project37/Project37/Assets.xcassets/)
  2. Extend the CardViewController.swift to handle the new card type by adding a new case to the card symbol enum and implementing render logic (Classic/Project37/Project37/CardViewController.swift)
  3. Update ViewController.swift to instantiate cards for the new symbol and shuffle them into the game board logic (Classic/Project37/Project37/ViewController.swift)
  4. Add sound effects by placing an MP3 file in Classic/Project37/Project37/Content/ and reference it in CardViewController for audio playback (Classic/Project37/Project37/Content/)

Add a New Core Data Entity and Display It

  1. Edit Classic/Project38/Project38/Project38.xcdatamodeld/Project38.xcdatamodel/contents to add a new Entity with Name, relationships, and attributes (Classic/Project38/Project38/Project38.xcdatamodeld/Project38.xcdatamodel/contents)
  2. In Xcode, select the new entity and use Editor > Create NSManagedObject Subclass to generate the +CoreDataClass.swift and +CoreDataProperties.swift files (Classic/Project38/Project38/)
  3. Update ViewController.swift to fetch the new entity using NSFetchRequest and display results in the table view's cellForRowAtIndexPath delegate method (Classic/Project38/Project38/ViewController.swift)
  4. Update DetailViewController.swift to accept and display the selected entity by binding properties from the master view controller (Classic/Project38/Project38/DetailViewController.swift)

Add a New WatchKit Complication

  1. Add new complication images to Classic/Project37/Project37 WatchKit Extension/Assets.xcassets/Complication.complicationset/ with Circular, Modular, and Utilitarian variants (Classic/Project37/Project37 WatchKit Extension/Assets.xcassets/Complication.complicationset/)
  2. Edit the storyboard at Classic/Project37/Project37 WatchKit App/Base.lproj/Interface.storyboard to add complication UI elements (Classic/Project37/Project37 WatchKit App/Base.lproj/Interface.storyboard)
  3. Update InterfaceController.swift to configure and display the new complication in the awakeWithContext lifecycle method (Classic/Project37/Project37 WatchKit Extension/InterfaceController.swift)

Apply Custom Styling to a View

  1. Create a new custom UIView subclass (similar to GradientView.swift) that overrides layoutSubviews and drawRect to apply custom styling (Classic/Project37/Project37/GradientView.swift)
  2. In Interface Builder (Main.storyboard), select the view you want to style and set its Class to your new custom view in the Identity Inspector (Classic/Project37/Project37/Base.lproj/Main.storyboard)
  3. Expose any configurable style properties (colors, gradients, borders) as @IBInspectable properties to allow design-time configuration in Interface Builder (Classic/Project37/Project37/GradientView.swift)

🔧Why these technologies

  • UIKit + Storyboards — Primary framework for iOS development in the tutorial era; Interface Builder provides visual layout for learners unfamiliar with code-based constraints.
  • Core Data — Demonstrates on-device persistence without requiring server infrastructure; Project 38 teaches relationship modeling and fetch request patterns.
  • WatchKit — Project 37 includes a watch extension to teach multi-target development and platform-specific UI patterns (complications, Interface Builder for watch).
  • SpriteKit (inferred from README) — Used for 2D game rendering in some projects; provides particle effects and sprite animations for game-focused tutorials.
  • Core Animation — CardViewController uses CATransaction for flip animations; teaches explicit animation control beyond UIView.animate.

⚖️Trade-offs already made

  • Use Storyboards instead of code-based UI layout

    • Why: Visual feedback helps beginners understand view hierarchy; reduces boilerplate Auto Layout code in tutorials.
    • Consequence: Storyboards do not scale well for large teams; merge conflicts are common. Modern SwiftUI folder exists separately to address this.
  • Include both Classic (UIKit) and SwiftUI editions

    • Why: Caters to learners at different skill levels and framework preferences; allows comparison between paradigms.
    • Consequence: Doubles maintenance burden; code duplication across two codebases. Repository must host ~600 files to cover both.
  • Embed third-party JSON library (SwiftyJSON) rather than import via CocoaPods

    • Why: Reduces dependency management overhead for tutorial followers; single file can be copied without package manager setup.
    • Consequence: Library version may become outdated; no automatic security updates. Maintainer must manually sync external code.
  • Use generated Core Data subclasses (Author+CoreDataClass, etc.)

    • Why: Xcode's automatic generation from .xcdatamodel teaches Core Data conventions and Entity relationships vis
    • Consequence: undefined

🪤Traps & gotchas

WatchKit Extension requires a paired iOS app host to run (can't test Watch app in simulator without the parent iOS app target). Storyboard-based projects require careful attention to outlet connections—broken IBOutlets will crash at runtime. Asset catalogs require exact Contents.json structure; missing or malformed JSON prevents Xcode from recognizing images. No visible package manager configuration (CocoaPods/SPM) means all frameworks must be built-in Apple frameworks—external dependencies would require manual integration.

🏗️Architecture

💡Concepts to learn

  • WatchKit Complications — Project37 includes a Complication.complicationset in Assets; understanding complications is essential to building useful watchOS apps that display data on the watch face, not just in the app UI
  • Asset Catalog and Image Scaling — The cardBack/cardCircle/cardCross/cardSquare/cardLines image sets with 1x/2x/3x variants demonstrate the standard iOS pattern for supporting multiple screen densities without code changes
  • MVC (Model-View-Controller) in UIKit — Classic projects use AppDelegate + ViewControllers; understanding MVC is foundational for UIKit development, even though SwiftUI projects move to MVVM
  • Storyboard-Based UI vs. Programmatic Layouts — Project37 uses storyboards (Interface.storyboard); learners must understand when storyboards are appropriate vs. programmatic UI, a common debate in iOS development
  • App Lifecycle and Delegates — AppDelegate and ExtensionDelegate handle app launch, background transitions, and resource cleanup; mastering the lifecycle is critical for all iOS/watchOS apps
  • SwiftUI Declarative Syntax — SwiftUI path teaches the paradigm shift from imperative UIKit callbacks to declarative UI composition; essential for modern iOS development targeting iOS 17+
  • SpriteKit 2D Game Framework — Classic projects include SpriteKit for game development; understanding nodes, scenes, physics, and rendering is unique to SpriteKit and absent from UIKit/SwiftUI tutorials
  • apple/swift-tutorials — Official Apple Swift tutorial content; complements HackingWithSwift as the authoritative source for Swift language features and standard library patterns
  • pointfreeco/swift-composable-architecture — Advanced Swift architecture library used in production apps; shows how HackingWithSwift's MVVM/MVC patterns scale to large codebases
  • raywenderlich/swift-algorithm-club — Algorithm and data structure implementations in Swift; pairs with HackingWithSwift for learning algorithmic thinking in Swift context
  • SwiftyJSON/SwiftyJSON — Popular Swift JSON parsing library; many HackingWithSwift projects likely need JSON handling, making this a natural next step for real-world code
  • Alamofire/Alamofire — Canonical HTTP networking library for iOS; HackingWithSwift projects teaching networking would benefit from studying how Alamofire wraps URLSession best practices

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add README.md files to each Classic project folder with setup and learning objectives

Each project (Project37, etc.) lacks individual documentation explaining what the project teaches, prerequisites, and how to build it. This helps new contributors and learners navigate the repo structure and understand each project's purpose without reading the main tutorial. Project37 already has scattered assets but no overview.

  • [ ] Create Classic/Project37/README.md documenting the project's learning goals (card matching game, animation, particle effects)
  • [ ] Document build requirements and Xcode version compatibility for the WatchKit app components
  • [ ] Add links to corresponding tutorial chapters on hackingwithswift.com
  • [ ] Repeat pattern for other Classic projects to ensure consistency

Create a CONTRIBUTING.md guide with project structure overview and validation checklist

The repo lacks contribution guidelines specific to the Hacking with Swift projects. New contributors don't know: (1) how projects are organized (Classic vs SwiftUI split), (2) which Xcode/iOS versions to target, (3) whether to update project.pbxproj files directly or use Xcode UI, (4) asset naming conventions (cardBack.png, cardCircle.png pattern). This is critical for maintaining consistency across 40+ projects.

  • [ ] Document the Classic vs SwiftUI folder structure and when to add projects to each
  • [ ] Specify required Xcode version (15+) and iOS deployment targets per project type
  • [ ] Clarify asset organization: imageset structure, @2x/@3x scaling requirements (evident from cardBack.imageset pattern)
  • [ ] Include checklist for submitting a new project: Assets.xcassets setup, Info.plist requirements, removal of build artifacts

Add a project manifest/index (projects.json or projects.yml) documenting all projects with metadata

The repo has 40+ projects but no machine-readable index. This would help: (1) contributors quickly identify which projects exist and what they cover, (2) enable automation (e.g., validate all projects build), (3) link projects to tutorial URLs. Currently, discovering what each project teaches requires manual exploration or external tutorial site.

  • [ ] Create projects.json at repo root with entries: {name, path, category (Classic/SwiftUI), tutorialUrl, requiredFrameworks, iosVersion}
  • [ ] Document Project37 as example: iOS card-matching game + WatchKit, requires SpriteKit, iOS 11+
  • [ ] Add script to validate file structure matches manifest (e.g., check project.pbxproj exists for each entry)
  • [ ] Update main README.md to reference the manifest for project discovery

🌿Good first issues

  • Add missing documentation comments to InterfaceController.swift and ExtensionDelegate.swift explaining WatchKit lifecycle methods (applicationDidFinishLaunching, applicationDidBecomeActive, etc.) for learners unfamiliar with watchOS patterns.
  • Create a README.md file inside Classic/Project37/ that explains the project goal, what watchOS/WatchKit concepts it teaches, and how to run it—mirroring what likely exists for other projects but is missing from the file list.
  • Add unit tests for card model logic (if Project37 contains game logic beyond UI)—create Tests/ folder with XCTestCase subclass to demonstrate testing patterns not shown in the tutorial code.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • e33c441 — Merge pull request #125 from lamtrinhdev/Update_Readme.md (twostraws)
  • 302a97a — Append What's new in Swift 6.2 and SwiftUI for iOS 26 in README.md (lamtrinhdev)
  • 432d623 — Merge pull request #123 from lamtrinhdev/Update_Readme.md (twostraws)
  • fa983ba — Append What's new in Swift 6.1 in README.md (lamtrinhdev)
  • 7b00e63 — Merge pull request #112 from lamtrinhdev/Update_Readme.md (twostraws)
  • e907ceb — Update URLs for "What's new..." articles for swift 6 and iOS 18 (lamtrinhdev)
  • 36d0208 — Now targeting iOS 17. (twostraws)
  • 9b7e910 — Bumping all remaining projects up to 19 to target iOS 17. (twostraws)
  • 702b6a7 — Merge pull request #97 from ishtiaq156/update-docs (twostraws)
  • 90ea823 — Cleaning part 3. (twostraws)

🔒Security observations

This is an educational codebase from the 'Hacking with Swift' tutorial series and is primarily designed for learning iOS development with UIKit and SpriteKit. No critical or high-severity vulnerabilities were identified in the static structure analysis. The codebase lacks dependency files (no Package.swift, Podfile, or Cartfile detected), reducing supply chain attack surface. However, typical security best practices for production applications (data encryption, secure credential storage, input validation) may not be fully implemented as this is educational material. The presence of Core Data usage and bundled media files suggests consideration should be given to encryption and integrity verification in any adapted production code. Overall security posture is reasonable for an educational project, but developers should not use this as a template for production applications without adding proper security hardening.

  • Low · Educational Project Without Security Hardening — Project-wide (Classic/Project37, Classic/Project38, etc.). This is an educational codebase from 'Hacking with Swift' tutorial series designed for learning purposes. While educational projects are typically not production-ready, they may lack security best practices that should be applied in real applications. Fix: Treat this as educational material only. When building production applications, implement proper security practices including input validation, secure API communication, data encryption, and secure credential management.
  • Low · Potential Core Data Usage Without Encryption — Classic/Project38/Project38/Author+CoreDataClass.swift, Classic/Project38/Project38/Commit+CoreDataClass.swift. Project38 contains Core Data models (Author+CoreDataClass.swift, Commit+CoreDataClass.swift) which suggest local database usage. Core Data stores data unencrypted by default on disk, which could expose sensitive information if the device is compromised. Fix: If storing sensitive data, implement Core Data encryption using NSFileProtectionComplete, use Keychain for sensitive credentials, or consider using encrypted database solutions like SQLCipher.
  • Low · Audio File Included Without Integrity Verification — Classic/Project37/Project37/Content/PhantomFromSpace.mp3. Project37 includes an MP3 audio file (PhantomFromSpace.mp3) that is bundled with the application. There is no apparent mechanism to verify the integrity of bundled media files. Fix: For production apps, implement integrity checks for bundled media files. Use code signing and verify bundle signatures at runtime, or implement hash verification for critical media assets.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · twostraws/HackingWithSwift — RepoPilot