Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ env:
SIM_DEVICE: iPhone 17
# Keep in sync with justfile's sim_os default. The Validate / Build & test
# steps below interpolate $SIM_OS into the xcodebuild -destination string.
SIM_OS: "26.1"
SIM_OS: "26.2"

jobs:
ci:
Expand Down Expand Up @@ -58,8 +58,8 @@ jobs:
- name: Install xcresultparser
run: brew install xcresultparser

- name: Select Xcode 26.1.1
run: sudo xcode-select -s /Applications/Xcode_26.1.1.app/Contents/Developer
- name: Select Xcode 26.2
run: sudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer

# Cache only the SPM source packages, not the whole DerivedData tree.
# Caching DerivedData also caches Clang's ModuleCache.noindex (.pcm
Expand All @@ -73,8 +73,8 @@ jobs:
uses: actions/cache@v4
with:
path: ~/Library/Developer/Xcode/DerivedData/NanoViewController-*/SourcePackages
key: spm-${{ runner.os }}-xcode-26.1.1-${{ hashFiles('**/Package.resolved') }}
restore-keys: spm-${{ runner.os }}-xcode-26.1.1-
key: spm-${{ runner.os }}-xcode-26.2-${{ hashFiles('**/Package.resolved') }}
restore-keys: spm-${{ runner.os }}-xcode-26.2-

- name: Runner info
run: |
Expand Down
2 changes: 1 addition & 1 deletion Examples/SignUpDemo/App/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import UIKit

Expand Down
2 changes: 1 addition & 1 deletion Examples/SignUpDemo/App/SceneDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import NanoViewControllerController
import UIKit
Expand Down
2 changes: 1 addition & 1 deletion Examples/SignUpDemo/Sources/AppCoordinator.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import NanoViewControllerController
import NanoViewControllerNavigation
Expand Down
2 changes: 1 addition & 1 deletion Examples/SignUpDemo/Sources/Home/HomeCoordinator.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import NanoViewControllerController
import NanoViewControllerNavigation
Expand Down
2 changes: 1 addition & 1 deletion Examples/SignUpDemo/Sources/Home/HomeScene.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import NanoViewControllerController

Expand Down
2 changes: 1 addition & 1 deletion Examples/SignUpDemo/Sources/Home/HomeView.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import NanoViewControllerCombine
Expand Down
2 changes: 1 addition & 1 deletion Examples/SignUpDemo/Sources/Home/HomeViewModel.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import NanoViewControllerController
Expand Down
2 changes: 1 addition & 1 deletion Examples/SignUpDemo/Sources/Models/SignedUpUser.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Foundation

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import NanoViewControllerController
import NanoViewControllerNavigation
Expand Down
2 changes: 1 addition & 1 deletion Examples/SignUpDemo/Sources/Onboarding/SignUpScene.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import NanoViewControllerController

Expand Down
2 changes: 1 addition & 1 deletion Examples/SignUpDemo/Sources/Onboarding/SignUpView.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import NanoViewControllerCombine
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import Foundation
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import Foundation
Expand Down
2 changes: 1 addition & 1 deletion Examples/SignUpDemo/Sources/Services/SignUpServicing.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine

Expand Down
2 changes: 1 addition & 1 deletion Sources/NanoViewControllerCombine/Binder.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Foundation

Expand Down
2 changes: 1 addition & 1 deletion Sources/NanoViewControllerCombine/Publisher+Extras.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import Foundation
Expand Down
2 changes: 1 addition & 1 deletion Sources/NanoViewControllerCombine/Publisher+Helpers.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import Foundation
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import UIKit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import UIKit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import UIKit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import UIKit
Expand Down
2 changes: 1 addition & 1 deletion Sources/NanoViewControllerCombine/UIView+Publishers.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import UIKit

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import UIKit

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import Foundation
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import UIKit

Expand Down
2 changes: 1 addition & 1 deletion Sources/NanoViewControllerController/ContentView.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import NanoViewControllerCore
import UIKit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Foundation

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import NanoViewControllerCombine
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import NanoViewControllerCombine
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import NanoViewControllerCombine
import NanoViewControllerCore
import NanoViewControllerNavigation

extension Coordinating {
/// Subscribes the coordinator to the controller's navigation publisher and
/// stores the resulting cancellable on the coordinator's bag.
/// Subscribes to the controller's navigation publisher and stashes the
/// cancellable on the scene itself, so re-subscribing through the inverse
/// helper (see ``subscribeToModalNavigation(of:handler:)``) cancels this
/// subscription instead of letting both sinks fire on every emission.
///
/// Used by the push-style hookup in
/// ``Coordinating/pushSceneInstance(_:animated:navigationPresentationCompletion:navigationHandler:)``.
Expand All @@ -17,37 +19,50 @@ extension Coordinating {
/// tests can invoke coordinator routing directly without driving the
/// view-model's Combine pipeline. Production callers don't see this
/// property unless they opt in via `@_spi(Testing) import`.
///
/// Clears ``NanoViewController/modalNavigationHandler`` to keep the two
/// SPI hooks mutually exclusive — the live handler is whichever helper
/// last subscribed.
func subscribeToNavigation<S: NanoViewController<V>, V: ContentView>(
of scene: S,
handler: @escaping (V.ViewModel.NavigationStep) -> Void
) {
scene.navigationHandler = handler
scene.navigation
scene.modalNavigationHandler = nil
scene.navigationSubscription = scene.navigation
.sinkOnMain { handler($0) }
.store(in: &cancellables)
}

/// Subscribes the coordinator to the controller's navigation publisher and
/// hands the caller's handler a `DismissScene` callback that dismisses
/// the controller with optional animation. Used by the modal-style hookups in
/// Subscribes to the controller's navigation publisher and hands the
/// caller's handler a `DismissScene` callback that dismisses the
/// controller with optional animation. Used by the modal-style hookups in
/// ``Coordinating/modallyPresent(scene:animated:presentationCompletion:navigationHandler:)``
/// and ``Coordinating/replaceAllScenes(with:animated:whenReplacingFinished:navigationHandler:)``.
///
/// Like the push-style variant, the cancellable lives on the scene so
/// that re-subscribing through ``subscribeToNavigation(of:handler:)``
/// cancels this subscription rather than leaving two live sinks routing
/// every emission to both handlers.
///
/// Side effect: stashes `handler` on
/// ``NanoViewController/modalNavigationHandler`` (an `@_spi(Testing)` hook).
/// Tests pass a spy ``DismissScene`` when invoking the handler so the
/// dismissal side-effect is observable without a real modal presentation.
///
/// Clears ``NanoViewController/navigationHandler`` to keep the two SPI
/// hooks mutually exclusive — the live handler is whichever helper last
/// subscribed.
func subscribeToModalNavigation<S: NanoViewController<V>, V: ContentView>(
of scene: S,
handler: @escaping ModalNavigationHandler<V.ViewModel>
) {
scene.modalNavigationHandler = handler
scene.navigation
scene.navigationHandler = nil
scene.navigationSubscription = scene.navigation
.sinkOnMain { [weak scene] step in
handler(step) { animated, completion in
scene?.dismiss(animated: animated, completion: completion)
}
}
.store(in: &cancellables)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import NanoViewControllerCombine
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import NanoViewControllerCombine
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import NanoViewControllerCombine
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import NanoViewControllerNavigation
import UIKit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import NanoViewControllerCore
import NanoViewControllerNavigation
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import Foundation
Expand Down
2 changes: 1 addition & 1 deletion Sources/NanoViewControllerController/InputType.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Foundation

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import NanoViewControllerCore
import UIKit
Expand Down
14 changes: 13 additions & 1 deletion Sources/NanoViewControllerController/NanoViewController.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import NanoViewControllerCore
Expand Down Expand Up @@ -205,6 +205,18 @@ open class NanoViewController<View: ContentView>: UIViewController {
@_spi(Testing)
public internal(set) var modalNavigationHandler: ((ViewModel.NavigationStep, @escaping DismissScene) -> Void)?

/// The Combine subscription forwarding ``navigation`` into the
/// coordinator's routing closure (either ``navigationHandler`` or
/// ``modalNavigationHandler``).
///
/// Lives on the scene rather than the coordinator's bag so that
/// re-subscribing through the inverse helper (push ↔ modal) cancels the
/// previous subscription — assigning a fresh `AnyCancellable` releases
/// (and cancels) the old one. This enforces "last subscriber wins" on
/// the Combine route, matching the mutual-exclusivity invariant the SPI
/// hook properties already promise.
var navigationSubscription: AnyCancellable?

/// Clock used to auto-dismiss toasts emitted via
/// ``InputFromController/toastSubject``.
///
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import NanoViewControllerCore
import UIKit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import UIKit

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import UIKit

Expand Down
2 changes: 1 addition & 1 deletion Sources/NanoViewControllerController/Toast.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import NanoViewControllerDIPrimitives
import NanoViewControllerNavigation
Expand Down
2 changes: 1 addition & 1 deletion Sources/NanoViewControllerController/ViewModelType.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Foundation
import NanoViewControllerCore
Expand Down
2 changes: 1 addition & 1 deletion Sources/NanoViewControllerController/ViewModelled.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import NanoViewControllerCombine
Expand Down
2 changes: 1 addition & 1 deletion Sources/NanoViewControllerCore/AbstractTarget.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)
// MIT License — Copyright (c) 2018-2026 Alexander Cyon - https://github.com/sajjon

import Combine
import Foundation
Expand Down
Loading
Loading