Sample CodeiOS 12.0+, iPadOS 12.0+, Mac Catalyst 12.0+Reviewed 2026-07-23View on Apple Developer

Delivering an exceptional accessibility experience

At a glance

Item Summary
Purpose Demonstrate custom actions, adjustable elements, grouped statistics, modal accessibility, and change notifications.
Architecture One UIKit view controller coordinates a small model and several specialized views.
State strategy currentlyFocusedDog is the controller’s source of truth and propagates to the carousel, statistics, and shelter views.
Boundary Single app target; no extension, persistence service, or custom protocol layer.

Project structure

ExceptionalAccessibility/
├── ViewController.swift
├── Dog.swift
├── DogCarouselContainerView.swift
├── DogStatsView.swift
├── DogModalView.swift
└── DogCollectionViewCell.swift

Files are organized by screen component rather than formal architectural layers.

Overall architecture

Reference code

ExceptionalAccessibility/ViewController.swift:32 — one property broadcasts the selected model (abridged).

var currentlyFocusedDog: Dog? {
    didSet {
        dogStatsView.dog = currentlyFocusedDog
        carouselContainerView.currentDog = currentlyFocusedDog
        shelterNameLabel.text = currentlyFocusedDog?.shelterName
        shelterInfoView.accessibilityLabel = currentlyFocusedDog?.shelterName
    }
}

Ownership and state

Ownership evidence

ExceptionalAccessibility/DogCarouselContainerView.swift:189 — the container lazily owns and invalidates its accessibility projection (abridged).

private var _accessibilityElements: [Any]?

override var accessibilityElements: [Any]? {
    if _accessibilityElements == nil {
        let element = CarouselAccessibilityElement(
            accessibilityContainer: self,
            dog: currentDog
        )
        self.carouselAccessibilityElement = element
    }
    return _accessibilityElements
}

The controller owns selection state. Each custom view owns only the accessibility objects derived from its current dog and clears its cache when that input changes.

Class and protocol design

The sample uses concrete UIKit subclasses: CarouselAccessibilityElement: UIAccessibilityElement, DogCarouselContainerView: UIView, and DogStatsView: UIView. ViewController directly adopts framework data-source/delegate protocols at ExceptionalAccessibility/ViewController.swift:15. There is no app-defined protocol because the components communicate through outlets and properties.

Access control

Symbol Access Why it fits
_accessibilityElements in carousel/stats private Cache consistency must remain inside each view (ExceptionalAccessibility/DogStatsView.swift:52).
Most outlets and model state internal default Storyboard wiring and the small sample share them across files.
Dog fields internal The value is target-local and directly rendered by several views.
Public API none The archive builds an application, not a library.

The underscore marks a backing cache; private enforces its invalidation contract. Broader internal visibility is educational convenience, not a published surface.

Logic ownership and placement

Logic Owner Placement reason
Current-dog propagation and collection scrolling ViewController It coordinates all screen components.
Adjustable VoiceOver behavior CarouselAccessibilityElement It is the semantic replacement for the carousel (ExceptionalAccessibility/DogCarouselContainerView.swift:133).
Grouping label pairs DogStatsView It knows label frames and content.
Modal isolation DogModalView The overlay declares itself modal at ExceptionalAccessibility/DogModalView.swift:51.

Design patterns

Pattern Evidence Purpose
Coordinator-by-controller currentlyFocusedDog.didSet Synchronizes multiple views from one selection.
Accessibility adapter Custom element turns a collection into an adjustable picker Changes semantics without changing the visual UI.
Cached derived view Accessibility element arrays persist until input changes Gives VoiceOver stable object identity.
Framework delegate Collection protocols on the controller Keeps the small screen direct.

Naming conventions

  • Domain names (Dog) stay separate from UI role suffixes (View, ViewController, Element).
  • currentDog and currentlyFocusedDog communicate selection semantics.
  • Accessibility overrides retain UIKit’s framework vocabulary.

Architecture takeaways

  • Keep one authoritative selection and push it to dependent components.
  • Cache custom accessibility elements when assistive navigation requires stable identity.
  • Place geometry-aware accessibility grouping inside the owning view.
  • The design is intentionally concrete and code-light; extra service or protocol layers would obscure the examples.

Source map

Source Role
ExceptionalAccessibility/Dog.swift:13 Domain value and fixtures
ExceptionalAccessibility/ViewController.swift:45 Custom actions and screen coordination
ExceptionalAccessibility/DogCarouselContainerView.swift:22 Adjustable custom element
ExceptionalAccessibility/DogStatsView.swift:28 Input-driven cache invalidation
ExceptionalAccessibility/DogModalView.swift:38 Overlay lifecycle
ExceptionalAccessibility/AppDelegate.swift:9 App entry point