Sample CodeiOS, iPadOS, Mac CatalystReviewed 2026-07-21View on Apple Developer

Implementing Peek and Pop

At a glance

Item Summary
Purpose Compares storyboard and code registration for legacy Peek and Pop, including preview quick actions.
App architecture A base table controller owns catalog behavior; two subclasses isolate storyboard-versus-code preview setup, and an injected detail controller mutates the selected model.
Main patterns Template Method inheritance, preview/commit, model injection, observer notifications, and model-owned change events.
Project style Small storyboard app with a dedicated Models/ folder and deliberately parallel feature variants.

Project structure

PeekPopNavigation/
├── ColorsViewControllerBase.swift
├── ColorsViewControllerCode.swift
├── ColorsViewControllerStoryboard.swift
├── ColorItemViewController.swift
├── Models/
│   ├── ColorData.swift
│   ├── ColorItem.swift
│   └── Notifications.swift
└── Base.lproj/Main.storyboard

Structure observations

  • The base controller contains all table, navigation, and notification behavior so each variant shows only its integration difference.
  • ColorsViewControllerStoryboard is intentionally empty; storyboard configuration is the implementation.
  • Model events are named in Notifications.swift, separate from the mutable model types that emit them.

Overall architecture

Reference code

PeekPopNavigation/ColorsViewControllerCode.swift:25 — the code variant builds the preview with the same ColorData and ColorItem references used by the list, then commits that configured controller.

func previewingContext(_ previewingContext: UIViewControllerPreviewing,
                       viewControllerForLocation location: CGPoint) -> UIViewController? {
    guard let indexPath = tableView.indexPathForRow(at: location),
        let cell = tableView.cellForRow(at: indexPath) else { return nil }

    previewingContext.sourceRect = cell.frame

    guard let viewController = storyboard?.instantiateViewController(
        withIdentifier: "ColorItemViewController") as? ColorItemViewController
        else { preconditionFailure("Expected a ColorItemViewController") }

    viewController.colorData = colorData
    viewController.colorItem = colorData.colors[indexPath.row]
    return viewController
}

func previewingContext(_ previewingContext: UIViewControllerPreviewing,
                       commit viewControllerToCommit: UIViewController) {
    navigationController?.pushViewController(viewControllerToCommit, animated: true)
}

Interpretation

Preview is not a copy of feature state. The preview and eventual committed controller share the original object references, so quick actions immediately affect the same catalog observed by the table screen.

Ownership and state

Ownership evidence

PeekPopNavigation/Models/ColorItem.swift:10 — each mutable property emits a model event; the owning data array remains in ColorData.

class ColorItem {
    // ...
}
Owner State Relationship Mutation authority
Each base-controller instance Its own ColorData Creates and retains Detail actions through injected reference
ColorData Ordered ColorItem array Owns catalog delete(_:)
ColorItem Name, color, starred flag Reference model Detail normal/preview actions
ColorItemViewController Selected data/item references Injected, not copied UI actions

Class and protocol design

Type Responsibility Design note
ColorsViewControllerBase Table source, normal segue, model-event handling Shared template for both integration variants
ColorsViewControllerCode Register previewing and implement preview/commit callbacks Focused framework adapter subclass
ColorsViewControllerStoryboard Mark storyboard-configured variant Empty by design
ColorItemViewController Present/mutate one color and expose preview actions Receives both item and owning collection
ColorData / ColorItem Own catalog and mutable item state Reference models broadcast changes

There is no app-defined protocol. The code variant conforms directly to the UIKit previewing delegate; the base-class seam is inheritance because the sample compares two setup mechanisms around identical behavior.

Access control

Symbol group Access Verified effect Rationale
All app types, properties, and methods implicit internal Any code in the sample target can access them. The source declares no private, fileprivate, or public members.
colorData implicit internal let Subclasses and detail injection can read the stable container reference. Shared behavior crosses the base/subclass boundary.
Detail model references implicit internal optionals Segue and preview code inject them across files. Required composition seam inside the target.
Notification names implicit internal static let Models and observers share typed names. Target-wide event vocabulary.

Reference code

PeekPopNavigation/ColorsViewControllerBase.swift:15 — the base exposes its stable model container to subclasses rather than widening anything to a public framework API.

class ColorsViewControllerBase: UITableViewController {
    // ...
}

Logic ownership and placement

Logic Owner Why it belongs there
Common table and navigation behavior Base controller Shared by both integration variants.
Code-based preview/commit Code subclass Isolates the API the sample is comparing.
Storyboard preview setup Storyboard resource/empty subclass Configuration itself is the demonstration.
Star/delete commands Detail controller Same commands serve normal and preview UI.
Change/delete notifications ColorItem / ColorData Event originates where mutation occurs.

Design patterns

Pattern Source evidence Purpose or tradeoff
Template Method base controller PeekPopNavigation/ColorsViewControllerBase.swift:15 Removes unrelated table code from the two preview variants.
Preview/commit PeekPopNavigation/ColorsViewControllerCode.swift:25 Configures once, then pushes the same controller on commit.
Dependency injection PeekPopNavigation/ColorsViewControllerBase.swift:58 Gives detail access to the selected item and deletion owner.
Observer notifications PeekPopNavigation/Models/ColorData.swift:27 Refreshes list UI after mutations from preview actions.

Naming conventions

  • Base, Code, and Storyboard suffixes make the comparison structure explicit.
  • ColorData names the collection owner; ColorItem names one mutable entity.
  • Notifications use past-tense events: colorItemUpdated and colorItemDeleted.
  • previewingContext names are inherited from UIKit; domain actions remain toggleStar and delete.

Architecture takeaways

  • Factor shared feature behavior away from alternative integration mechanisms when teaching or testing platform APIs.
  • Inject the same model reference into preview and committed presentation when actions must have immediate effect.
  • Emit change events from mutation owners, but scope observers by object identity when multiple catalogs exist.
  • Internal access is sufficient for an app target; absence of access modifiers should not be described as a public API.

Source map

Source file Relevant symbols
PeekPopNavigation/ColorsViewControllerBase.swift Shared list, segue, and observers
PeekPopNavigation/ColorsViewControllerCode.swift Code preview/commit adapter
PeekPopNavigation/ColorsViewControllerStoryboard.swift Storyboard variant marker
PeekPopNavigation/ColorItemViewController.swift Detail and preview quick actions
PeekPopNavigation/Models/ColorData.swift Catalog owner and deletion
PeekPopNavigation/Models/ColorItem.swift Mutable item and update events
PeekPopNavigation/Models/Notifications.swift Typed notification names