airbnb/epoxy-ios
62.7
Adequate · 1 October 2026
18.6k
lines of production code
Swift
primary language
2
measurements over time
What this system is
Epoxy is a declarative UI framework for iOS and macOS that manages complex view hierarchies, including collection views, navigation stacks, and modal presentations, through a model-based diffing system. It provides specialized modules for handling bottom and top bar stacks with safe area management, as well as a SwiftUI-compatible layout system for composing horizontal and vertical groups. The library supports both UIKit and SwiftUI integration, allowing developers to build and update UI components using result builders and type-safe model definitions.
How it got here
2016–2020 — Declarative UI and modular architecture
19 changes.
This period focused on modernizing the library by removing legacy UIKit APIs and introducing a comprehensive declarative model system with core diffing infrastructure. It established a modular architecture through the EpoxyBars and EpoxyNavigationController components, enabling structured management of view controllers and UI bars. The work also standardized distribution via CocoaPods and SPM while expanding example projects to demonstrate SwiftUI integration and complex layout patterns.
2021–2022 — EpoxyCollectionView and LayoutGroups expansion
27 changes.
This period focused on expanding the library with the initial release of EpoxyCollectionView, introducing robust diffing, prefetching, and native support for both FlowLayout and CompositionalLayout. Concurrently, the EpoxyLayoutGroups module was added to provide declarative horizontal and vertical layout containers, mirroring SwiftUI's HStack and VStack. The work also included significant infrastructure updates for strict concurrency safety and the introduction of SwiftUI hosting capabilities to bridge UIKit views into SwiftUI hierarchies.
Features
Add LayoutGroups example view controllers
The example app now includes a new set of view controllers in the LayoutGroups section to demonstrate the declarative layout API. These examples showcase various layout configurations, including horizontal and vertical groups, inline group views, dynamic content updates, and specific UI patterns like message lists and todo items.
Example/EpoxyExample/ViewControllers/LayoutGroups · high confidence
Add LayoutGroups example views demonstrating declarative UI composition
The EpoxyExample app now includes a new set of view components in the LayoutGroups directory that demonstrate the declarative API for creating components. These examples, such as ActionButtonRow, AlignableTextRow, CheckboxRow, and MessageRow, utilize the EpoxyLayoutGroups framework to build complex layouts using VGroup and HGroup items. The diff also introduces supporting element views (Label, Button, IconView, ColorView) and a comparison view (MessageRowStackView) that uses UIStackView to highlight the differences in API and performance between the new LayoutGroups approach and traditional StackViews.
Example/EpoxyExample/Views/LayoutGroups · high confidence
Add README example view controllers for Epoxy features
Added a set of example view controllers in the \Example/EpoxyExample/ViewControllers/Readme\ directory that demonstrate Epoxy's core capabilities, including collection views (Counter, Tap Me), bottom bars (Bottom Button), navigation stacks (Form Navigation), and modal presentations (Presentation). These examples utilize the new result builders (\@ItemModelBuilder\, \@BarModelBuilder\, \@NavigationModelBuilder\, \@PresentationModelBuilder\) to declaratively define UI components and behaviors, providing concrete source code references for the README documentation.
Example/EpoxyExample/ViewControllers/Readme · high confidence
Add adaptive edge insets and customizable group update animations
Users can now define layout group spacing that adapts to device size classes and accessibility settings via the new \GroupEdgeInsets\ type, which supports fixed, adaptive, and accessibility-aware values. Additionally, the \LayoutGroupUpdateAnimation\ type allows customization of how group updates are animated, including a convenience factory for spring animations with configurable duration, delay, damping, and velocity.
Sources/EpoxyLayoutGroups/Types · high confidence
Add example app icon and launch assets
The Epoxy example app now includes a complete set of app icon assets for iPhone, iPad, and the App Store, along with a launch screen storyboard and an updated Info.plist configuration. This ensures the example app displays correctly on all supported iOS devices and meets App Store submission requirements.
Example/EpoxyExample/Assets · high confidence
Add example data models for Epoxy demonstrations
New data source files (BeloIpsum, Example, LayoutGroupsExample, ReadmeExample) have been added to the Example/EpoxyExample/Data directory to support the project's demonstration apps. BeloIpsum provides a seeded lorem ipsum generator for populating UI elements, while the Example, LayoutGroupsExample, and ReadmeExample enums define the available demo scenarios (such as SwiftUI bridges, layout groups, and basic collection views) along with their titles and descriptions for the example navigation interface.
Example/EpoxyExample/Data · high confidence
Add native support for UICollectionViewFlowLayout and UICollectionViewCompositionalLayout
Users can now configure layout properties directly on Epoxy models for both \UICollectionViewFlowLayout\ and \UICollectionViewCompositionalLayout\. For FlowLayout, \ItemModel\ and \SectionModel\ expose properties to control item size, section insets, line/interitem spacing, and header/footer reference sizes, which are applied via the collection view's delegate. For Compositional Layout, a new \compositionalLayoutSectionProvider\ allows models to dynamically define \NSCollectionLayoutSection\ structures based on the layout environment, enabling complex, data-driven layouts without manual delegate implementation.
Sources/EpoxyCollectionView/Layouts · high confidence
Adds declarative group item creation and optional constraint helpers
This change introduces a new \EpoxyableView+GroupItem\ extension that provides a declarative API for creating \GroupItem\ models from styled views, supporting various combinations of content, style, and behaviors. It also adds \NSLayoutConstraint+Optional\ helpers to safely activate and deactivate arrays of optional constraints by filtering out nil values.
Sources/EpoxyLayoutGroups/Extensions · high confidence
Declarative CollectionViewController with safe area and configuration options
Introduces a new \CollectionViewController\ that manages collection view sections declaratively via \SectionModel\ arrays and supports result builders for concise section and item definition. The controller allows initialization without subclassing by exposing a \makeCollectionView()\ method for custom collection view setup, and includes a \CollectionViewConfiguration\ that enables toggling whether the collection view anchors to the view's safe area layout guide for leading and trailing constraints.
Sources/EpoxyCollectionView/ViewControllers · high confidence
Initial release of EpoxyCollectionView with configurable update strategies and prefetching
This change introduces the \CollectionView\ component, a \UICollectionView\ wrapper that manages content updates via an \UpdateStrategy\ enum (supporting animated batch updates, non-animated batch updates, or standard \reloadData\). The component includes a \CollectionViewConfiguration\ singleton that enables cell prefetching and accurate scroll-to-item behavior by default, while also providing delegates for item display, accessibility, reordering, and layout transitions to handle user interactions and visibility events.
Sources/EpoxyCollectionView/CollectionView · high confidence
Introduce BarModel API for defining and configuring bar views
This change introduces the \BarModel\ type and its supporting infrastructure (\AnyBarModel\, \BarModeling\ protocol, and result builders) within the \Sources/EpoxyBars/BarModel\ directory. It provides a structured way to define bar content, manage view lifecycle events (such as \willDisplay\ and \didSelect\), and configure behaviors. The update also adds convenience extensions for \StyledView\ and \SwiftUI.View\, allowing developers to easily create bar models from UIKit views conforming to \ContentConfigurableView\ and \BehaviorsConfigurableView\, or directly from SwiftUI views.
Sources/EpoxyBars/BarModel · high confidence
Introduce BottomBarInstaller for managing bottom bar stacks
Added the BottomBarInstaller component, which allows developers to install and manage a stack of bar views at the bottom of a view controller. This installer automatically handles safe area insets to ensure scrollable content is properly inset by the bar height, and includes an optional keyboard avoidance feature that offsets the bar stack when the keyboard appears. The implementation includes the BottomBarContainer view, the BottomBarInstaller coordinator, and the BottomBarsProviding protocol for easy integration.
Sources/EpoxyBars/BottomBarInstaller · high confidence
Introduce EpoxyBars bar installation and safe-area management
This change introduces the core EpoxyBars infrastructure for managing fixed top and bottom bars within view controllers. It adds the BarInstaller to handle the lifecycle (install/uninstall) of bar stacks, and the BarContainer protocol with BarContainerInsetBehavior to control how bars affect safe area and scroll view content insets (supporting barHeightSafeArea, barHeightContentInset, and none modes). The BarStackView manages the arrangement and selection of individual bar views, while BarWrapperView handles per-bar model updates and layout margin adjustments. A new BarInstallerConfiguration allows global or per-instance customization of how bar models are applied to containers, and utility extensions on UIView, UIScrollView, and UIViewController support safe area and transform detection.
Sources/EpoxyBars/BarInstaller · high confidence
Introduce EpoxyLayoutGroups for declarative horizontal and vertical layouts
Adds the EpoxyLayoutGroups module, providing \HGroup\ and \VGroup\ as declarative layout containers that model SwiftUI's \HStack\ and \VStack\. These groups support configurable item spacing, alignment (including accessibility-specific reflow), and animated updates with smooth transitions. The implementation includes a \Constrainable\ protocol for Auto Layout integration, \LayoutSpacer\ for explicit spacing, and result-builder syntax for defining group contents.
Sources/EpoxyLayoutGroups/Groups · high confidence
Introduce SwiftUI hosting infrastructure for Epoxy views
This change adds the core infrastructure for embedding UIKit-based Epoxy views within SwiftUI hierarchies. It introduces \EpoxySwiftUIHostingView\ and \EpoxySwiftUIHostingController\ to manage the lifecycle, sizing, and safe-area handling of UIKit views inside SwiftUI, including specific fixes for cell sizing bugs and keyboard avoidance. It also provides \SwiftUIView\, a \UIViewRepresentable\ wrapper that allows any \UIView\ to be used in SwiftUI with configurable sizing strategies and update closures, and adds helper extensions like \swiftUIView\ on \StyledView\ to simplify bridging existing Epoxy views into SwiftUI environments.
Sources/EpoxyCore/SwiftUI · high confidence
Introduce TopBarInstaller for managing top bar stacks and safe area insets
This change introduces the \TopBarInstaller\ and \TopBarContainer\ components within the EpoxyBars library, providing a structured way to manage a stack of bar views at the top of a view controller. The installer automatically adjusts the view controller's safe area insets based on the height of the bar stack, ensuring scrollable content is correctly inset. It includes configurable behaviors for handling status bar visibility (via \StatusBarInsetBehavior\) and scroll view edge pinning, along with a \TopBarsProviding\ protocol to simplify bar model integration in view controllers.
Sources/EpoxyBars/TopBarInstaller · high confidence
Introduce bar coordination and dynamic height invalidation
This change introduces the \BarCoordinator\ system, allowing bars to maintain local state and trigger updates outside the normal data flow via the \BarCoordinating\ protocol and \CoordinatedBarModel\. It adds \BarCoordinatorProperty\ to propagate properties across bar stacks and \HeightInvalidatingBarView\ to support animated height changes within a \BarStackView\. Additionally, \SafeAreaLayoutMarginsBarView\ is added to control how safe area and layout margins interact.
Sources/EpoxyBars/BarCoordinator · high confidence
Introduce core diffing infrastructure for collections and sections
This change introduces the foundational diffing engine for Epoxy, adding protocols and algorithms to compute minimal change sets between collections of data. It defines the \Diffable\ and \DiffableSection\ protocols, which require a \diffIdentifier\ (now non-optional) and equality checks to identify items. The core logic in \Collection+Diff.swift\ implements algorithms to detect inserts, deletes, updates, and moves, returning structured results in \IndexChangeset\, \IndexPathChangeset\, \IndexSetChangeset\, and \SectionedChangeset\. This enables the library to efficiently update UI components by calculating exactly what has changed between old and new data states, including specific handling for duplicate identifiers.
Sources/EpoxyCore/Diffing · high confidence
Introduce declarative modal presentation models for UIKit view controllers
This change adds the EpoxyPresentations module, enabling developers to drive modal presentations and dismissals in UIKit using a declarative, model-based approach similar to Epoxy's list handling. It introduces the \PresentationModel\ struct to define what should be presented, a \PresentationQueue\ to manage transitions and handle rapid state changes by queuing pending presentations, and a \UIViewController\ extension (\setPresentation(\_:animated:)\) to apply these models. Additionally, it provides a \@PresentationModelBuilder\ result builder, allowing for concise, conditional DSL-style construction of optional presentation models.
Sources/EpoxyPresentations · high confidence
Introduce internal EpoxyCollectionView infrastructure for diffing, data management, and scrolling
This change adds the internal implementation files for the EpoxyCollectionView, establishing the core mechanics for rendering and interaction. It introduces CollectionViewData and CollectionViewChangeset to manage section/item snapshots and compute minimal diffs for updates. CollectionViewDataSource handles the mapping of this data to UIKit's UICollectionViewDataSource protocol, including view differentiator registration. CollectionViewScrollToItemHelper provides a custom scrolling solution using CADisplayLink to ensure accurate positioning for self-sizing cells, including support for high-refresh-rate displays (up to 120 FPS). ReuseIDStore manages the generation and caching of cell reuse identifiers based on view differentiators.
Sources/EpoxyCollectionView/CollectionView/Internal · high confidence
Introduce keyboard-aware bar stack and position watcher
Added \InputAccessoryBarStackView\ to display a stack of bars as a keyboard input accessory, automatically adjusting its bottom layout margin to match the safe area when the keyboard is hidden. Introduced \KeyboardPositionWatcher\ to monitor keyboard show/hide events and calculate the overlap with specific views, enabling consumers to animate UI in sync with the keyboard or automatically adjust a scroll view's bottom content inset.
Sources/EpoxyBars/Keyboard · high confidence
Introduces EpoxyLayoutGroups model types for declarative nested layouts
This change adds the model layer for the new EpoxyLayoutGroups feature, introducing \GroupItem\, \HGroupItem\, \VGroupItem\, \SpacerItem\, and \StaticGroupItem\ to represent items within horizontal and vertical groups. It includes \AnyGroupItem\ for type-erasure and \GroupModelBuilder\ for declarative syntax, along with provider protocols (e.g., \PaddingProviding\, \HorizontalAlignmentProviding\) that allow these items to configure alignment, padding, and accessibility behaviors.
Sources/EpoxyLayoutGroups/Models · high confidence
Introduces HGroupView and VGroupView for declarative layout groups
Adds HGroupView and VGroupView, UIView-backed implementations of HGroup and VGroup that conform to EpoxyableView, allowing them to be used directly within Epoxy's CollectionView. These views support declarative styling via Style structs (including edge insets and nested group styles) and content binding through Content models, with layout margins automatically updating on trait changes and safe area insets disabled by default to match UIStackView-like hugging behavior.
Sources/EpoxyLayoutGroups/Views · high confidence
New SupplementaryItemModel API for configuring collection view supplementary views
This change introduces a new \SupplementaryItemModel\ type and its supporting infrastructure (\AnySupplementaryItemModel\, \SupplementaryItemModeling\ protocol) for configuring supplementary views (such as headers and footers) in a \UICollectionView\. The new API allows users to define supplementary items with specific content and behaviors using closures (\setContent\, \setBehaviors\) and provides convenience extensions for UIKit's \StyledView\ and SwiftUI \View\ types to easily create these models. This replaces or supplements previous mechanisms for handling supplementary items, offering a more structured and type-safe approach to managing their lifecycle and configuration within the collection view.
Sources/EpoxyCollectionView/Models/SupplementaryItemModel · high confidence
New SwiftUI example views for bridging UIKit and Epoxy
The example app now includes new SwiftUI view controllers that demonstrate bridging UIKit views into SwiftUI and embedding SwiftUI views within Epoxy collections. Specifically, \EpoxyInSwiftUISizingStrategiesViewController\ showcases various sizing strategies for bridged UIKit labels, while \SwiftUIInEpoxyViewController\ and \SwiftUIInEpoxyResizingViewController\ provide examples of rendering SwiftUI rows inside an Epoxy \UICollectionView\, including support for expandable rows with local state.
Example/EpoxyExample/ViewControllers/SwiftUI · high confidence
New example views for buttons, cards, and text rows
The Example/EpoxyExample/Views directory now includes several new view components to demonstrate Epoxy usage: ButtonRow for tap interactions, CardContainer for styled containers with shadows and borders, ColorView for displaying colored blocks, CustomSizingView for self-sizing labels, ImageMarquee and ImageRow for image display, TextFieldRow for text input with change callbacks, and TextRow for styled text with selection and highlight behaviors. These views implement the EpoxyableView protocol and serve as concrete examples for building declarative UI components.
Example/EpoxyExample/Views · high confidence
New view protocols for lifecycle, selection, and accessibility events
Added five new public protocols to the \EpoxyCollectionView\ view layer to allow custom views to react to specific collection view events. \DisplayRespondingView\ enables views to handle display lifecycle events via \didDisplay(\_:)\, while \HighlightableView\ and \SelectableView\ provide hooks for highlight and selection interactions respectively. \EphemeralCachedStateView\ allows views to manage and restore ephemeral state (such as expansion state) automatically during cell recycling, and \AccessibilityCustomizedView\ permits views to override default accessibility behaviors like \accessibilityElementsHidden\.
Sources/EpoxyCollectionView/Views · high confidence
Unified Epoxy module import
Developers can now import the entire Epoxy framework using a single \import Epoxy\ statement. The new \Exports.swift\ file re-exports all sub-modules (EpoxyBars, EpoxyCollectionView, EpoxyCore, EpoxyLayoutGroups, EpoxyNavigationController, and EpoxyPresentations), simplifying dependency management and reducing boilerplate in source files.
Sources/Epoxy · high confidence
Removals
Removed legacy UIKit List and TableView APIs
The legacy \ListStructure\, \ListItemStructure\, \QuickDiff\, and \TableView\ APIs have been removed from the repository. These files, which provided an older declarative approach for driving \UITableView\ content via diffing, are no longer part of the library, requiring users to migrate to the current \EpoxyCollectionView\ and \EpoxyNavigationController\ modules for declarative UI construction.
(repo-wide) · high confidence
Behavioural changes
Added Xcode workspace configuration for EpoxyCore and Example projects
The Epoxy workspace now includes a standard Xcode workspace file that references the EpoxyCore and EpoxyExample projects, along with the IDE workspace checks plist to suppress the 32-bit warning. This change establishes the workspace structure required to build and run the library and its example app, supporting the broader effort to add macOS and tvOS targets.
Epoxy.xcworkspace · medium confidence
Declarative navigation stack management via NavigationModel
The EpoxyNavigationController now manages its visible view controllers declaratively using an array of NavigationModels rather than imperative UIKit calls. Users must update the navigation stack by calling setStack(\_:animated:) with a new array of models, which applies only the differences between the previous and new stacks. Manual management methods like pushViewController and setViewControllers are disabled to enforce this pattern. The system supports nested navigation flows, handles duplicate dataIDs across sections, and exposes lifecycle callbacks (didShow, didHide, didAdd, didRemove) on NavigationModel to react to view controller visibility and removal events.
Sources/EpoxyNavigationController · high confidence
EpoxyLogger now prevents release-build crashes from assertions
The new EpoxyLogger class allows consumers to intercept Epoxy assertions and warning messages, and its default implementation correctly respects the Swift compiler's -O optimization flag. This change fixes a bug where assertions would unexpectedly crash in release builds, ensuring that Epoxy's internal checks no longer cause app crashes in production.
Sources/EpoxyCore/Logging · high confidence
Improved sizing configurability for UIKit views in SwiftUI
Users can now explicitly control how UIKit views hosted in SwiftUI are sized by setting a \sizing\ strategy (e.g., intrinsic, proposed, or automatic) via the new \sizing()\ modifier on \MeasuringViewRepresentable\. This change introduces \MeasuringViewRepresentable\ and updates \SwiftUIMeasurementContainer\ to support multiple measurement strategies, allowing for more predictable layout behavior when bridging UIKit components into SwiftUI layouts.
Sources/EpoxyCore/SwiftUI/LayoutUtilities · high confidence
Initialized Xcode workspace structure
The example project now includes the necessary Xcode workspace configuration files (contents.xcworkspacedata and IDEWorkspaceChecks.plist), establishing the standard workspace structure required for the project to open correctly in Xcode.
Example/EpoxyExample.xcodeproj/project.xcworkspace · medium confidence
Internal refactoring for model property updates and class references
This change introduces internal infrastructure to support better model handling and debugging. It adds the \AnyEpoxyModelProperty\ protocol to allow erased model properties to perform updates via their strategies, and introduces the \ClassReference\ struct to provide a human-readable, hashable wrapper around \AnyClass\ values, improving debuggability compared to raw \ObjectIdentifier\ usage.
Sources/EpoxyCore/Model/Internal · medium confidence
Introduce internal collection view reusables and selection styling
This change introduces the internal \CollectionViewCell\ and \CollectionViewReusableView\ classes, which now handle view pinning, visual highlight states (including custom selected background colors), and layout attribute fitting via the new \FittingPrioritiesProvidingLayoutAttributes\ protocol. It also adds the \ItemSelectionStyle\ enum to define how selected items are visually styled and the \ItemCellView\ protocol to standardize cell state access. These components form the foundational rendering and sizing logic for collection view items and supplementary views within this module.
Sources/EpoxyCollectionView/CollectionView/ReusableViews · high confidence
Introduces EpoxyModeled protocol and property-based model storage
The EpoxyCore library now uses a new \EpoxyModeled\ protocol as the base for all declarative UI models, replacing the previous model structure. This change introduces a generic, key-path-based property system (\EpoxyModelProperty\) and a dedicated storage container (\EpoxyModelStorage\) that allows models to store and merge configuration values dynamically. Users can now define custom model properties in extensions and use chainable setters that leverage an \UpdateStrategy\ to handle value conflicts during model updates. Additionally, a result builder (\EpoxyModelArrayBuilder\) is provided to enable a more concise DSL for constructing arrays of these models.
Sources/EpoxyCore/Model · high confidence
Introduces strict concurrency annotations and new view configuration protocols
View protocols in EpoxyCore are now annotated with @preconcurrency and @MainActor to enforce strict concurrency safety. The library introduces dedicated protocols for view configuration: StyledView for invariant initialization parameters, ContentConfigurableView for Equatable updatable properties, and BehaviorsConfigurableView for non-Equatable properties like callbacks. These are composed into the EpoxyableView typealias, and ViewType is abstracted to support both UIKit (UIView) and AppKit (NSView) platforms.
Sources/EpoxyCore/Views · high confidence
Item model system refactored with type erasure and new provider protocols
The item model architecture in \Sources/EpoxyCollectionView/Models/ItemModel\ has been restructured to support a more modular and type-safe API. A new \AnyItemModel\ type-eraser is introduced to wrap concrete \ItemModel\ instances, enabling heterogeneous collections while preserving access to specific model properties via passthrough storage. The core \ItemModel\ now relies on a set of new, granular protocols (such as \DidChangeStateProviding\, \IsMovableProviding\, \SelectionStyleProviding\, and \SupplementaryItemsProviding\) to manage cell behaviors, state changes, and layout metadata. This change also adds \ItemCellMetadata\ and \ItemCellState\ structs to standardize the context passed during cell configuration and lifecycle events, and introduces \ItemModelBuilder\ result builders for cleaner DSL-based array construction.
Sources/EpoxyCollectionView/Models/ItemModel · high confidence
New model provider protocols for view lifecycle and configuration
The \Sources/EpoxyCore/Model/Providers\ directory now includes a set of new protocols that allow models to explicitly provide view lifecycle callbacks, content, and configuration details. Specifically, \SetContentProviding\ and \SetBehaviorsProviding\ enable models to define closures for setting view content and behaviors (like tap handlers) during updates. Lifecycle events are now handled via \WillDisplayProviding\, \DidDisplayProviding\, and \DidEndDisplayingProviding\, which expose corresponding closures to the model. Additionally, \MakeViewProviding\ allows models to supply a custom view construction closure, while \StyleIDProviding\, \DataIDProviding\, and \ErasedContentProviding\ provide standardized ways to manage view reuse identifiers, stable data IDs, and type-erased content equality. \ViewDifferentiatorProviding\ introduces a \ViewDifferentiator\ struct to facilitate cell reuse identifier generation based on view type and style ID.
Sources/EpoxyCore/Model/Providers · high confidence
Reorganized example project structure with new view controllers and layout examples
The EpoxyExample project has been restructured to reflect modern best practices, introducing a clearer directory hierarchy with dedicated groups for Application, Assets, Data, Extensions, ViewControllers, and Views. This update adds numerous new example view controllers to demonstrate specific features, including LayoutGroups (e.g., \LayoutGroupsExampleViewController\, \DynamicLayoutGroupsViewController\), SwiftUI integration (e.g., \EpoxyInSwiftUIViewController\, \SwiftUIInEpoxyViewController\), and various UI components like TextFields, FlowLayouts, and CompositionalLayouts. The project now includes specific examples for complex declarative layouts, message stacks, and card stacks, providing developers with more comprehensive reference implementations for using Epoxy in both UIKit and SwiftUI contexts.
Example/EpoxyExample.xcodeproj · high confidence
Restructured example app with declarative navigation and new product demo
The example application has been restructured to use a declarative navigation model via \NavigationModel\ and result builders, replacing the previous setup. This change introduces a new \MainViewController\ that manages the navigation stack using \@NavigationModelBuilder\, allowing for cleaner state-driven UI updates. Additionally, a new \ProductViewController\ example demonstrates the use of \BarModelBuilder\ for bottom bars and \PresentationModelBuilder\ for presenting modals, showcasing the library's declarative APIs for complex view hierarchies and interactions.
Example/EpoxyExample/ViewControllers · high confidence
SectionModel now requires an explicit dataID
The SectionModel initializer now mandates an explicit dataID parameter, making it a required field for identifying sections. The previous initializers that accepted only items are deprecated and will be removed in a future version, ensuring that every section has a stable identifier for diffing and state management.
Sources/EpoxyCollectionView/Models/SectionModel · high confidence
Updated Xcode scheme configuration for EpoxyExample
The Xcode scheme for the EpoxyExample app has been reconfigured to align with modern project structures. The scheme now explicitly enables parallel builds and implicit dependency building, and is set to build the application for testing, running, profiling, archiving, and analyzing. Additionally, the scheme targets Xcode version 12.20 and configures the launch, profile, and archive actions to use the Debug and Release configurations respectively, ensuring consistent behavior for developers running or debugging the example app.
Example/EpoxyExample.xcodeproj/xcshareddata · high confidence
Test coverage
Added test coverage for EpoxyBars, CollectionView, Core, and LayoutGroups
Added comprehensive test suites for the EpoxyBars, EpoxyCollectionView, EpoxyCore, and EpoxyLayoutGroups modules. The new tests verify bar installer behavior (including safe area insets and layout margins), collection view visibility callbacks and flow layout configuration, core diffing and model builder logic, and layout group constraint inheritance.
Tests · high confidence
Dependencies
Add CocoaPods and Swift Package Manager support
The Epoxy declarative UI library is now available for installation via CocoaPods and Swift Package Manager (SPM). This change introduces a unified \Package.swift\ manifest and a suite of podspecs (Epoxy, EpoxyCore, EpoxyCollectionView, EpoxyBars, EpoxyLayoutGroups, EpoxyNavigationController, and EpoxyPresentations) to manage the library's modular components. It also establishes a consistent dependency graph for development and testing tools, pinning versions for Quick, Nimble, CwlCatchException, CwlPreconditionTesting, AirbnbSwift, and swift-argument-parser in the resolved files.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Score
- CAI 67 → 63 (-4.7)
- Rubric changed (rubric-2026.09.11 → rubric-2026.09.18) — scores are not directly comparable.
Lenses
- Code Health 97 → 97 (-0.2)
- Architecture 95 → 91 (-3.5)
- Maturity 52 → 52 (+0.4)
- Readiness 67 → 68 (+1.2)
- Security 91 → 95 (+3.6)
- Performance 62 (new)
Resolved (3)
- Duplicated block (11 lines × 2) (Example/EpoxyExample/ViewControllers/ProductViewController.swift)
- Further sole-owners (lower concentration)
- Off-boarding risk: anonymized user #1
New (15)
- Coverage not measured — Swift suite
- Duplicated block (10 lines × 2) (Example/EpoxyExample/ViewControllers/LayoutGroups/MessagesUIStackViewViewController.swift)
- Duplicated block (14 lines × 2) (Example/EpoxyExample/ViewControllers/CollectionView/CompositionalLayoutViewController.swift)
- Duplicated block (22 lines × 2) (Example/EpoxyExample/Data/LayoutGroupsExample.swift)
- Duplicated block (30 lines × 2) (Example/EpoxyExample/Data/Example.swift)
- Duplicated block (9 lines × 2) (Example/EpoxyExample/Extensions/UICollectionViewCompositionalLayout+List.swift)
- Duplicated block (9 lines × 2) (Sources/EpoxyLayoutGroups/Models/GroupItem.swift)
- Outdated: cwlcatchexception
- Outdated: cwlpreconditiontesting
- Outdated: nimble
- Outdated: swift
- Outdated: swift-argument-parser
- Projects may be oversized for their cohesion
- The naming convention for erasing to a type-erased wrapper is consistent (eraseToAny...), but AnyBarModel and AnyItemModel have an eraseToAny... method that returns themselves (or a type-erased version of themselves), which is redundant if they are already type-erased. Specifically, AnyBarModel is a type-erased wrapper, yet it has eraseToAnyBarModel(). Similarly for AnyItemModel and AnySupplementaryItemModel. This suggests that AnyBarModel might not be fully type-erased in the sense of hiding the underlying concrete type's implementation details, or it's a redundant method for a type that is already 'Any'. If AnyBarModel is the final type-erased form, this method should not exist or should be internal. If it exists to allow chaining, it's acceptable but slightly confusing.
- While the method name setBars is consistent across these types, the semantic intent differs slightly between the 'Installer' types (which manage lifecycle/installation state) and the 'StackView' types (which are pure UI containers). More importantly, BarStackView and InputAccessoryBarStackView expose setBars directly on the view, whereas BottomBarInstaller and TopBarInstaller expose it on the installer object which then updates the container. This creates a split in responsibility: should the view or the installer be the primary entry point for updating bars? In BottomBarInstaller/TopBarInstaller, the view is internal/managed, but in BarStackView, the view is the public API. This is a minor architectural inconsistency in ownership, but the signatures themselves are consistent.
Changes since last survey
- 1 commits — 1 feature/other, 0 fixes
By area
- (root) — 1 commit
Notable commits
- change: Prepare Epoxy 0.12.0 release (#186)
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
airbnb/epoxy-ios was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 1 October 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 5317bb67d6f7a97c438fb4e89c7a944083dad67d — the exact code this score is about.
- Scored under rubric-2026.09.18 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-e569280dd5e2.