diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f16a6f..fec0264 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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: @@ -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 @@ -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: | diff --git a/Examples/SignUpDemo/App/AppDelegate.swift b/Examples/SignUpDemo/App/AppDelegate.swift index 09bdda1..5ac5bcf 100644 --- a/Examples/SignUpDemo/App/AppDelegate.swift +++ b/Examples/SignUpDemo/App/AppDelegate.swift @@ -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 diff --git a/Examples/SignUpDemo/App/SceneDelegate.swift b/Examples/SignUpDemo/App/SceneDelegate.swift index fbb4ac6..8ac4919 100644 --- a/Examples/SignUpDemo/App/SceneDelegate.swift +++ b/Examples/SignUpDemo/App/SceneDelegate.swift @@ -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 diff --git a/Examples/SignUpDemo/Sources/AppCoordinator.swift b/Examples/SignUpDemo/Sources/AppCoordinator.swift index e77e28e..23b0841 100644 --- a/Examples/SignUpDemo/Sources/AppCoordinator.swift +++ b/Examples/SignUpDemo/Sources/AppCoordinator.swift @@ -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 diff --git a/Examples/SignUpDemo/Sources/Home/HomeCoordinator.swift b/Examples/SignUpDemo/Sources/Home/HomeCoordinator.swift index 8076526..3a688a3 100644 --- a/Examples/SignUpDemo/Sources/Home/HomeCoordinator.swift +++ b/Examples/SignUpDemo/Sources/Home/HomeCoordinator.swift @@ -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 diff --git a/Examples/SignUpDemo/Sources/Home/HomeScene.swift b/Examples/SignUpDemo/Sources/Home/HomeScene.swift index 9c568d8..b91a3d1 100644 --- a/Examples/SignUpDemo/Sources/Home/HomeScene.swift +++ b/Examples/SignUpDemo/Sources/Home/HomeScene.swift @@ -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 diff --git a/Examples/SignUpDemo/Sources/Home/HomeView.swift b/Examples/SignUpDemo/Sources/Home/HomeView.swift index 448a5e9..bdc3a59 100644 --- a/Examples/SignUpDemo/Sources/Home/HomeView.swift +++ b/Examples/SignUpDemo/Sources/Home/HomeView.swift @@ -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 diff --git a/Examples/SignUpDemo/Sources/Home/HomeViewModel.swift b/Examples/SignUpDemo/Sources/Home/HomeViewModel.swift index 3a5e91c..9b6e714 100644 --- a/Examples/SignUpDemo/Sources/Home/HomeViewModel.swift +++ b/Examples/SignUpDemo/Sources/Home/HomeViewModel.swift @@ -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 diff --git a/Examples/SignUpDemo/Sources/Models/SignedUpUser.swift b/Examples/SignUpDemo/Sources/Models/SignedUpUser.swift index 9fe08f6..3ae734b 100644 --- a/Examples/SignUpDemo/Sources/Models/SignedUpUser.swift +++ b/Examples/SignUpDemo/Sources/Models/SignedUpUser.swift @@ -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 diff --git a/Examples/SignUpDemo/Sources/Onboarding/OnboardingCoordinator.swift b/Examples/SignUpDemo/Sources/Onboarding/OnboardingCoordinator.swift index bbd711e..88fef35 100644 --- a/Examples/SignUpDemo/Sources/Onboarding/OnboardingCoordinator.swift +++ b/Examples/SignUpDemo/Sources/Onboarding/OnboardingCoordinator.swift @@ -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 diff --git a/Examples/SignUpDemo/Sources/Onboarding/SignUpScene.swift b/Examples/SignUpDemo/Sources/Onboarding/SignUpScene.swift index 8592034..e7b1c6f 100644 --- a/Examples/SignUpDemo/Sources/Onboarding/SignUpScene.swift +++ b/Examples/SignUpDemo/Sources/Onboarding/SignUpScene.swift @@ -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 diff --git a/Examples/SignUpDemo/Sources/Onboarding/SignUpView.swift b/Examples/SignUpDemo/Sources/Onboarding/SignUpView.swift index b20cc39..9052e45 100644 --- a/Examples/SignUpDemo/Sources/Onboarding/SignUpView.swift +++ b/Examples/SignUpDemo/Sources/Onboarding/SignUpView.swift @@ -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 diff --git a/Examples/SignUpDemo/Sources/Onboarding/SignUpViewModel.swift b/Examples/SignUpDemo/Sources/Onboarding/SignUpViewModel.swift index 3a93450..d97a83b 100644 --- a/Examples/SignUpDemo/Sources/Onboarding/SignUpViewModel.swift +++ b/Examples/SignUpDemo/Sources/Onboarding/SignUpViewModel.swift @@ -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 diff --git a/Examples/SignUpDemo/Sources/Services/DummySignUpService.swift b/Examples/SignUpDemo/Sources/Services/DummySignUpService.swift index fd0910e..e8d0068 100644 --- a/Examples/SignUpDemo/Sources/Services/DummySignUpService.swift +++ b/Examples/SignUpDemo/Sources/Services/DummySignUpService.swift @@ -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 diff --git a/Examples/SignUpDemo/Sources/Services/SignUpServicing.swift b/Examples/SignUpDemo/Sources/Services/SignUpServicing.swift index 45f3f29..ecd36d2 100644 --- a/Examples/SignUpDemo/Sources/Services/SignUpServicing.swift +++ b/Examples/SignUpDemo/Sources/Services/SignUpServicing.swift @@ -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 diff --git a/Sources/NanoViewControllerCombine/Binder.swift b/Sources/NanoViewControllerCombine/Binder.swift index e73b3e2..43bb27a 100644 --- a/Sources/NanoViewControllerCombine/Binder.swift +++ b/Sources/NanoViewControllerCombine/Binder.swift @@ -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 diff --git a/Sources/NanoViewControllerCombine/Publisher+Extras.swift b/Sources/NanoViewControllerCombine/Publisher+Extras.swift index b395454..f72435e 100644 --- a/Sources/NanoViewControllerCombine/Publisher+Extras.swift +++ b/Sources/NanoViewControllerCombine/Publisher+Extras.swift @@ -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 diff --git a/Sources/NanoViewControllerCombine/Publisher+Helpers.swift b/Sources/NanoViewControllerCombine/Publisher+Helpers.swift index e518ab0..3fecf08 100644 --- a/Sources/NanoViewControllerCombine/Publisher+Helpers.swift +++ b/Sources/NanoViewControllerCombine/Publisher+Helpers.swift @@ -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 diff --git a/Sources/NanoViewControllerCombine/Publisher+Operators.swift b/Sources/NanoViewControllerCombine/Publisher+Operators.swift index a107d0f..4b5675e 100644 --- a/Sources/NanoViewControllerCombine/Publisher+Operators.swift +++ b/Sources/NanoViewControllerCombine/Publisher+Operators.swift @@ -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 diff --git a/Sources/NanoViewControllerCombine/UIControl+Publisher.swift b/Sources/NanoViewControllerCombine/UIControl+Publisher.swift index 2bc1978..bab6880 100644 --- a/Sources/NanoViewControllerCombine/UIControl+Publisher.swift +++ b/Sources/NanoViewControllerCombine/UIControl+Publisher.swift @@ -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 diff --git a/Sources/NanoViewControllerCombine/UIControl+Publishers.swift b/Sources/NanoViewControllerCombine/UIControl+Publishers.swift index f688892..29beda6 100644 --- a/Sources/NanoViewControllerCombine/UIControl+Publishers.swift +++ b/Sources/NanoViewControllerCombine/UIControl+Publishers.swift @@ -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 diff --git a/Sources/NanoViewControllerCombine/UITextField+Publishers.swift b/Sources/NanoViewControllerCombine/UITextField+Publishers.swift index 0b42550..f20dd99 100644 --- a/Sources/NanoViewControllerCombine/UITextField+Publishers.swift +++ b/Sources/NanoViewControllerCombine/UITextField+Publishers.swift @@ -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 diff --git a/Sources/NanoViewControllerCombine/UIView+Publishers.swift b/Sources/NanoViewControllerCombine/UIView+Publishers.swift index 525ec56..fa7e303 100644 --- a/Sources/NanoViewControllerCombine/UIView+Publishers.swift +++ b/Sources/NanoViewControllerCombine/UIView+Publishers.swift @@ -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 diff --git a/Sources/NanoViewControllerController/AbstractController.swift b/Sources/NanoViewControllerController/AbstractController.swift index 6f81b50..86a363e 100644 --- a/Sources/NanoViewControllerController/AbstractController.swift +++ b/Sources/NanoViewControllerController/AbstractController.swift @@ -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 diff --git a/Sources/NanoViewControllerController/AbstractViewModel.swift b/Sources/NanoViewControllerController/AbstractViewModel.swift index f06ece1..12c1933 100644 --- a/Sources/NanoViewControllerController/AbstractViewModel.swift +++ b/Sources/NanoViewControllerController/AbstractViewModel.swift @@ -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 diff --git a/Sources/NanoViewControllerController/BarButtonContent.swift b/Sources/NanoViewControllerController/BarButtonContent.swift index 64b132b..0e39636 100644 --- a/Sources/NanoViewControllerController/BarButtonContent.swift +++ b/Sources/NanoViewControllerController/BarButtonContent.swift @@ -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 diff --git a/Sources/NanoViewControllerController/ContentView.swift b/Sources/NanoViewControllerController/ContentView.swift index f122986..f631293 100644 --- a/Sources/NanoViewControllerController/ContentView.swift +++ b/Sources/NanoViewControllerController/ContentView.swift @@ -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 diff --git a/Sources/NanoViewControllerController/ControllerConfig.swift b/Sources/NanoViewControllerController/ControllerConfig.swift index d184510..1ec6add 100644 --- a/Sources/NanoViewControllerController/ControllerConfig.swift +++ b/Sources/NanoViewControllerController/ControllerConfig.swift @@ -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 diff --git a/Sources/NanoViewControllerController/Coordinating+Child+ModalPresent.swift b/Sources/NanoViewControllerController/Coordinating+Child+ModalPresent.swift index c29ec15..f587f31 100644 --- a/Sources/NanoViewControllerController/Coordinating+Child+ModalPresent.swift +++ b/Sources/NanoViewControllerController/Coordinating+Child+ModalPresent.swift @@ -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 diff --git a/Sources/NanoViewControllerController/Coordinating+Child+Start.swift b/Sources/NanoViewControllerController/Coordinating+Child+Start.swift index f05dd84..b4623c9 100644 --- a/Sources/NanoViewControllerController/Coordinating+Child+Start.swift +++ b/Sources/NanoViewControllerController/Coordinating+Child+Start.swift @@ -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 diff --git a/Sources/NanoViewControllerController/Coordinating+NanoViewController+NavigationHelpers.swift b/Sources/NanoViewControllerController/Coordinating+NanoViewController+NavigationHelpers.swift index 1461640..628e179 100644 --- a/Sources/NanoViewControllerController/Coordinating+NanoViewController+NavigationHelpers.swift +++ b/Sources/NanoViewControllerController/Coordinating+NanoViewController+NavigationHelpers.swift @@ -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 @@ -6,8 +6,10 @@ 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:)``. @@ -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, 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, V: ContentView>( of scene: S, handler: @escaping ModalNavigationHandler ) { 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) } } diff --git a/Sources/NanoViewControllerController/Coordinating+NanoViewController+Present.swift b/Sources/NanoViewControllerController/Coordinating+NanoViewController+Present.swift index 717c108..d4f5a1a 100644 --- a/Sources/NanoViewControllerController/Coordinating+NanoViewController+Present.swift +++ b/Sources/NanoViewControllerController/Coordinating+NanoViewController+Present.swift @@ -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 diff --git a/Sources/NanoViewControllerController/Coordinating+NanoViewController+Push.swift b/Sources/NanoViewControllerController/Coordinating+NanoViewController+Push.swift index c927351..bb38537 100644 --- a/Sources/NanoViewControllerController/Coordinating+NanoViewController+Push.swift +++ b/Sources/NanoViewControllerController/Coordinating+NanoViewController+Push.swift @@ -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 diff --git a/Sources/NanoViewControllerController/Coordinating+NanoViewController+Replace.swift b/Sources/NanoViewControllerController/Coordinating+NanoViewController+Replace.swift index a584aa0..4ab9771 100644 --- a/Sources/NanoViewControllerController/Coordinating+NanoViewController+Replace.swift +++ b/Sources/NanoViewControllerController/Coordinating+NanoViewController+Replace.swift @@ -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 diff --git a/Sources/NanoViewControllerController/Coordinating+NavigationStack.swift b/Sources/NanoViewControllerController/Coordinating+NavigationStack.swift index 0c65032..825ff95 100644 --- a/Sources/NanoViewControllerController/Coordinating+NavigationStack.swift +++ b/Sources/NanoViewControllerController/Coordinating+NavigationStack.swift @@ -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 diff --git a/Sources/NanoViewControllerController/Coordinating+Stack.swift b/Sources/NanoViewControllerController/Coordinating+Stack.swift index 6a15c34..c7628c6 100644 --- a/Sources/NanoViewControllerController/Coordinating+Stack.swift +++ b/Sources/NanoViewControllerController/Coordinating+Stack.swift @@ -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 diff --git a/Sources/NanoViewControllerController/InputFromController.swift b/Sources/NanoViewControllerController/InputFromController.swift index 1075dd2..61ec9a3 100644 --- a/Sources/NanoViewControllerController/InputFromController.swift +++ b/Sources/NanoViewControllerController/InputFromController.swift @@ -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 diff --git a/Sources/NanoViewControllerController/InputType.swift b/Sources/NanoViewControllerController/InputType.swift index 26f3c3f..99952fc 100644 --- a/Sources/NanoViewControllerController/InputType.swift +++ b/Sources/NanoViewControllerController/InputType.swift @@ -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 diff --git a/Sources/NanoViewControllerController/NanoViewController+BarButtonContent.swift b/Sources/NanoViewControllerController/NanoViewController+BarButtonContent.swift index f949730..c2f10cf 100644 --- a/Sources/NanoViewControllerController/NanoViewController+BarButtonContent.swift +++ b/Sources/NanoViewControllerController/NanoViewController+BarButtonContent.swift @@ -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 diff --git a/Sources/NanoViewControllerController/NanoViewController.swift b/Sources/NanoViewControllerController/NanoViewController.swift index c789512..6798023 100644 --- a/Sources/NanoViewControllerController/NanoViewController.swift +++ b/Sources/NanoViewControllerController/NanoViewController.swift @@ -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 @@ -205,6 +205,18 @@ open class NanoViewController: 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``. /// diff --git a/Sources/NanoViewControllerController/NanoViewControllerWithoutVM.swift b/Sources/NanoViewControllerController/NanoViewControllerWithoutVM.swift index f17a2e1..6b24549 100644 --- a/Sources/NanoViewControllerController/NanoViewControllerWithoutVM.swift +++ b/Sources/NanoViewControllerController/NanoViewControllerWithoutVM.swift @@ -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 diff --git a/Sources/NanoViewControllerController/NavigationBarLayout.swift b/Sources/NanoViewControllerController/NavigationBarLayout.swift index e850548..15c3410 100644 --- a/Sources/NanoViewControllerController/NavigationBarLayout.swift +++ b/Sources/NanoViewControllerController/NavigationBarLayout.swift @@ -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 diff --git a/Sources/NanoViewControllerController/NavigationBarLayoutingNavigationController.swift b/Sources/NanoViewControllerController/NavigationBarLayoutingNavigationController.swift index 4de3962..15b5e34 100644 --- a/Sources/NanoViewControllerController/NavigationBarLayoutingNavigationController.swift +++ b/Sources/NanoViewControllerController/NavigationBarLayoutingNavigationController.swift @@ -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 diff --git a/Sources/NanoViewControllerController/Toast.swift b/Sources/NanoViewControllerController/Toast.swift index d64e411..a41d46d 100644 --- a/Sources/NanoViewControllerController/Toast.swift +++ b/Sources/NanoViewControllerController/Toast.swift @@ -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 diff --git a/Sources/NanoViewControllerController/ViewModelType.swift b/Sources/NanoViewControllerController/ViewModelType.swift index effb199..e2a21c5 100644 --- a/Sources/NanoViewControllerController/ViewModelType.swift +++ b/Sources/NanoViewControllerController/ViewModelType.swift @@ -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 diff --git a/Sources/NanoViewControllerController/ViewModelled.swift b/Sources/NanoViewControllerController/ViewModelled.swift index 07bb8be..fec0d3a 100644 --- a/Sources/NanoViewControllerController/ViewModelled.swift +++ b/Sources/NanoViewControllerController/ViewModelled.swift @@ -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 diff --git a/Sources/NanoViewControllerCore/AbstractTarget.swift b/Sources/NanoViewControllerCore/AbstractTarget.swift index 9395c59..2f6877d 100644 --- a/Sources/NanoViewControllerCore/AbstractTarget.swift +++ b/Sources/NanoViewControllerCore/AbstractTarget.swift @@ -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 diff --git a/Sources/NanoViewControllerCore/ActivityIndicator.swift b/Sources/NanoViewControllerCore/ActivityIndicator.swift index febd432..96cea8e 100644 --- a/Sources/NanoViewControllerCore/ActivityIndicator.swift +++ b/Sources/NanoViewControllerCore/ActivityIndicator.swift @@ -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 diff --git a/Sources/NanoViewControllerCore/BindingsBuilder.swift b/Sources/NanoViewControllerCore/BindingsBuilder.swift index 8c36d1c..b802243 100644 --- a/Sources/NanoViewControllerCore/BindingsBuilder.swift +++ b/Sources/NanoViewControllerCore/BindingsBuilder.swift @@ -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 diff --git a/Sources/NanoViewControllerCore/EmptyInitializable.swift b/Sources/NanoViewControllerCore/EmptyInitializable.swift index e8e7fc7..38b1180 100644 --- a/Sources/NanoViewControllerCore/EmptyInitializable.swift +++ b/Sources/NanoViewControllerCore/EmptyInitializable.swift @@ -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 diff --git a/Sources/NanoViewControllerCore/ErrorTracker.swift b/Sources/NanoViewControllerCore/ErrorTracker.swift index 2eea8f3..1a89a31 100644 --- a/Sources/NanoViewControllerCore/ErrorTracker.swift +++ b/Sources/NanoViewControllerCore/ErrorTracker.swift @@ -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 diff --git a/Sources/NanoViewControllerCore/Never+Helpers.swift b/Sources/NanoViewControllerCore/Never+Helpers.swift index 6080e80..e1bb487 100644 --- a/Sources/NanoViewControllerCore/Never+Helpers.swift +++ b/Sources/NanoViewControllerCore/Never+Helpers.swift @@ -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 diff --git a/Sources/NanoViewControllerCore/Output.swift b/Sources/NanoViewControllerCore/Output.swift index c388534..35f113d 100644 --- a/Sources/NanoViewControllerCore/Output.swift +++ b/Sources/NanoViewControllerCore/Output.swift @@ -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 diff --git a/Sources/NanoViewControllerDIPrimitives/Clock.swift b/Sources/NanoViewControllerDIPrimitives/Clock.swift index 88bcb19..2076e1a 100644 --- a/Sources/NanoViewControllerDIPrimitives/Clock.swift +++ b/Sources/NanoViewControllerDIPrimitives/Clock.swift @@ -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 diff --git a/Sources/NanoViewControllerDIPrimitives/DateProvider.swift b/Sources/NanoViewControllerDIPrimitives/DateProvider.swift index af6f458..1cd8d95 100644 --- a/Sources/NanoViewControllerDIPrimitives/DateProvider.swift +++ b/Sources/NanoViewControllerDIPrimitives/DateProvider.swift @@ -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 diff --git a/Sources/NanoViewControllerDIPrimitives/HapticFeedback.swift b/Sources/NanoViewControllerDIPrimitives/HapticFeedback.swift index 358b57d..bb5faf0 100644 --- a/Sources/NanoViewControllerDIPrimitives/HapticFeedback.swift +++ b/Sources/NanoViewControllerDIPrimitives/HapticFeedback.swift @@ -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 diff --git a/Sources/NanoViewControllerDIPrimitives/MainScheduler.swift b/Sources/NanoViewControllerDIPrimitives/MainScheduler.swift index d92f09d..4203d97 100644 --- a/Sources/NanoViewControllerDIPrimitives/MainScheduler.swift +++ b/Sources/NanoViewControllerDIPrimitives/MainScheduler.swift @@ -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 diff --git a/Sources/NanoViewControllerDIPrimitives/Pasteboard.swift b/Sources/NanoViewControllerDIPrimitives/Pasteboard.swift index eb17707..8697f06 100644 --- a/Sources/NanoViewControllerDIPrimitives/Pasteboard.swift +++ b/Sources/NanoViewControllerDIPrimitives/Pasteboard.swift @@ -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 diff --git a/Sources/NanoViewControllerDIPrimitives/UrlOpener.swift b/Sources/NanoViewControllerDIPrimitives/UrlOpener.swift index 657ff40..394ebab 100644 --- a/Sources/NanoViewControllerDIPrimitives/UrlOpener.swift +++ b/Sources/NanoViewControllerDIPrimitives/UrlOpener.swift @@ -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 diff --git a/Sources/NanoViewControllerNavigation/BaseCoordinator.swift b/Sources/NanoViewControllerNavigation/BaseCoordinator.swift index e2e0509..3dade6f 100644 --- a/Sources/NanoViewControllerNavigation/BaseCoordinator.swift +++ b/Sources/NanoViewControllerNavigation/BaseCoordinator.swift @@ -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 diff --git a/Sources/NanoViewControllerNavigation/Coordinating.swift b/Sources/NanoViewControllerNavigation/Coordinating.swift index 060418b..40d8bf3 100644 --- a/Sources/NanoViewControllerNavigation/Coordinating.swift +++ b/Sources/NanoViewControllerNavigation/Coordinating.swift @@ -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 diff --git a/Sources/NanoViewControllerNavigation/CoordinatorTransition.swift b/Sources/NanoViewControllerNavigation/CoordinatorTransition.swift index e91e195..baa2800 100644 --- a/Sources/NanoViewControllerNavigation/CoordinatorTransition.swift +++ b/Sources/NanoViewControllerNavigation/CoordinatorTransition.swift @@ -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 diff --git a/Sources/NanoViewControllerNavigation/Navigating.swift b/Sources/NanoViewControllerNavigation/Navigating.swift index 2f79f4f..e8b404f 100644 --- a/Sources/NanoViewControllerNavigation/Navigating.swift +++ b/Sources/NanoViewControllerNavigation/Navigating.swift @@ -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 /// Type capable of navigating — declares which navigation steps it can emit. /// diff --git a/Sources/NanoViewControllerNavigation/Navigator.swift b/Sources/NanoViewControllerNavigation/Navigator.swift index 4ed7bac..606cfd7 100644 --- a/Sources/NanoViewControllerNavigation/Navigator.swift +++ b/Sources/NanoViewControllerNavigation/Navigator.swift @@ -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 diff --git a/Sources/NanoViewControllerSceneViews/AbstractSceneView.swift b/Sources/NanoViewControllerSceneViews/AbstractSceneView.swift index bdaef3d..bd2a3f7 100644 --- a/Sources/NanoViewControllerSceneViews/AbstractSceneView.swift +++ b/Sources/NanoViewControllerSceneViews/AbstractSceneView.swift @@ -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 diff --git a/Sources/NanoViewControllerSceneViews/BaseScrollableStackViewOwner.swift b/Sources/NanoViewControllerSceneViews/BaseScrollableStackViewOwner.swift index 6ca3166..2b9d054 100644 --- a/Sources/NanoViewControllerSceneViews/BaseScrollableStackViewOwner.swift +++ b/Sources/NanoViewControllerSceneViews/BaseScrollableStackViewOwner.swift @@ -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 diff --git a/Sources/NanoViewControllerSceneViews/BaseTableViewOwner.swift b/Sources/NanoViewControllerSceneViews/BaseTableViewOwner.swift index 5e95809..49bffc6 100644 --- a/Sources/NanoViewControllerSceneViews/BaseTableViewOwner.swift +++ b/Sources/NanoViewControllerSceneViews/BaseTableViewOwner.swift @@ -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 diff --git a/Sources/NanoViewControllerSceneViews/CellConfigurable.swift b/Sources/NanoViewControllerSceneViews/CellConfigurable.swift index da28bf3..693d419 100644 --- a/Sources/NanoViewControllerSceneViews/CellConfigurable.swift +++ b/Sources/NanoViewControllerSceneViews/CellConfigurable.swift @@ -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 diff --git a/Sources/NanoViewControllerSceneViews/ClassIdentifiable.swift b/Sources/NanoViewControllerSceneViews/ClassIdentifiable.swift index 65a4716..f41b4d5 100644 --- a/Sources/NanoViewControllerSceneViews/ClassIdentifiable.swift +++ b/Sources/NanoViewControllerSceneViews/ClassIdentifiable.swift @@ -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 diff --git a/Sources/NanoViewControllerSceneViews/ContentViewProvider.swift b/Sources/NanoViewControllerSceneViews/ContentViewProvider.swift index adbcfd1..83a686c 100644 --- a/Sources/NanoViewControllerSceneViews/ContentViewProvider.swift +++ b/Sources/NanoViewControllerSceneViews/ContentViewProvider.swift @@ -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 diff --git a/Sources/NanoViewControllerSceneViews/PullToRefreshCapable.swift b/Sources/NanoViewControllerSceneViews/PullToRefreshCapable.swift index 41786ea..48b9277 100644 --- a/Sources/NanoViewControllerSceneViews/PullToRefreshCapable.swift +++ b/Sources/NanoViewControllerSceneViews/PullToRefreshCapable.swift @@ -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 diff --git a/Sources/NanoViewControllerSceneViews/ScrollViewOwner.swift b/Sources/NanoViewControllerSceneViews/ScrollViewOwner.swift index 485d41a..a62b54c 100644 --- a/Sources/NanoViewControllerSceneViews/ScrollViewOwner.swift +++ b/Sources/NanoViewControllerSceneViews/ScrollViewOwner.swift @@ -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 diff --git a/Sources/NanoViewControllerSceneViews/SelectionPublishing.swift b/Sources/NanoViewControllerSceneViews/SelectionPublishing.swift index 83a34e8..66f9045 100644 --- a/Sources/NanoViewControllerSceneViews/SelectionPublishing.swift +++ b/Sources/NanoViewControllerSceneViews/SelectionPublishing.swift @@ -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 diff --git a/Sources/NanoViewControllerSceneViews/SingleCellTypeTableView.swift b/Sources/NanoViewControllerSceneViews/SingleCellTypeTableView.swift index a8007f0..bed6d4b 100644 --- a/Sources/NanoViewControllerSceneViews/SingleCellTypeTableView.swift +++ b/Sources/NanoViewControllerSceneViews/SingleCellTypeTableView.swift @@ -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 diff --git a/Sources/NanoViewControllerSceneViews/TableViewOwner.swift b/Sources/NanoViewControllerSceneViews/TableViewOwner.swift index dad666d..43e789a 100644 --- a/Sources/NanoViewControllerSceneViews/TableViewOwner.swift +++ b/Sources/NanoViewControllerSceneViews/TableViewOwner.swift @@ -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 diff --git a/Tests/NanoViewControllerCombineTests/BinderTests.swift b/Tests/NanoViewControllerCombineTests/BinderTests.swift index 7051c04..6b6c626 100644 --- a/Tests/NanoViewControllerCombineTests/BinderTests.swift +++ b/Tests/NanoViewControllerCombineTests/BinderTests.swift @@ -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 @testable import NanoViewControllerCombine diff --git a/Tests/NanoViewControllerCombineTests/PublisherExtrasTests.swift b/Tests/NanoViewControllerCombineTests/PublisherExtrasTests.swift index e6d7f1a..815f060 100644 --- a/Tests/NanoViewControllerCombineTests/PublisherExtrasTests.swift +++ b/Tests/NanoViewControllerCombineTests/PublisherExtrasTests.swift @@ -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 @testable import NanoViewControllerCombine diff --git a/Tests/NanoViewControllerCombineTests/PublisherHelpersTests.swift b/Tests/NanoViewControllerCombineTests/PublisherHelpersTests.swift index af80236..b977f84 100644 --- a/Tests/NanoViewControllerCombineTests/PublisherHelpersTests.swift +++ b/Tests/NanoViewControllerCombineTests/PublisherHelpersTests.swift @@ -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 @testable import NanoViewControllerCombine diff --git a/Tests/NanoViewControllerCombineTests/SinkOnMainTests.swift b/Tests/NanoViewControllerCombineTests/SinkOnMainTests.swift index 9fd65a9..1e80147 100644 --- a/Tests/NanoViewControllerCombineTests/SinkOnMainTests.swift +++ b/Tests/NanoViewControllerCombineTests/SinkOnMainTests.swift @@ -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 @testable import NanoViewControllerCombine diff --git a/Tests/NanoViewControllerCombineTests/UIControlBindersTests.swift b/Tests/NanoViewControllerCombineTests/UIControlBindersTests.swift index e03a7b7..4e09e04 100644 --- a/Tests/NanoViewControllerCombineTests/UIControlBindersTests.swift +++ b/Tests/NanoViewControllerCombineTests/UIControlBindersTests.swift @@ -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 @testable import NanoViewControllerCombine diff --git a/Tests/NanoViewControllerCombineTests/UIControlPublisherDeadControlTests.swift b/Tests/NanoViewControllerCombineTests/UIControlPublisherDeadControlTests.swift index d38dd50..70b8002 100644 --- a/Tests/NanoViewControllerCombineTests/UIControlPublisherDeadControlTests.swift +++ b/Tests/NanoViewControllerCombineTests/UIControlPublisherDeadControlTests.swift @@ -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 @testable import NanoViewControllerCombine diff --git a/Tests/NanoViewControllerCombineTests/UIControlPublisherTests.swift b/Tests/NanoViewControllerCombineTests/UIControlPublisherTests.swift index 5be8360..ea92cf7 100644 --- a/Tests/NanoViewControllerCombineTests/UIControlPublisherTests.swift +++ b/Tests/NanoViewControllerCombineTests/UIControlPublisherTests.swift @@ -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 @testable import NanoViewControllerCombine diff --git a/Tests/NanoViewControllerCombineTests/UITextFieldPublishersTests.swift b/Tests/NanoViewControllerCombineTests/UITextFieldPublishersTests.swift index 9cbf5d5..def2265 100644 --- a/Tests/NanoViewControllerCombineTests/UITextFieldPublishersTests.swift +++ b/Tests/NanoViewControllerCombineTests/UITextFieldPublishersTests.swift @@ -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 @testable import NanoViewControllerCombine diff --git a/Tests/NanoViewControllerCombineTests/UIViewBindersTests.swift b/Tests/NanoViewControllerCombineTests/UIViewBindersTests.swift index 5eb0c67..e04035a 100644 --- a/Tests/NanoViewControllerCombineTests/UIViewBindersTests.swift +++ b/Tests/NanoViewControllerCombineTests/UIViewBindersTests.swift @@ -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 @testable import NanoViewControllerCombine import UIKit diff --git a/Tests/NanoViewControllerCombineTests/WithLatestFromCompletionTests.swift b/Tests/NanoViewControllerCombineTests/WithLatestFromCompletionTests.swift index d1932c6..94d6d8b 100644 --- a/Tests/NanoViewControllerCombineTests/WithLatestFromCompletionTests.swift +++ b/Tests/NanoViewControllerCombineTests/WithLatestFromCompletionTests.swift @@ -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 @testable import NanoViewControllerCombine diff --git a/Tests/NanoViewControllerControllerTests/AbstractViewModelTests.swift b/Tests/NanoViewControllerControllerTests/AbstractViewModelTests.swift index ea73517..0b7679d 100644 --- a/Tests/NanoViewControllerControllerTests/AbstractViewModelTests.swift +++ b/Tests/NanoViewControllerControllerTests/AbstractViewModelTests.swift @@ -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 @testable import NanoViewControllerController diff --git a/Tests/NanoViewControllerControllerTests/CoordinatorHelperTests.swift b/Tests/NanoViewControllerControllerTests/CoordinatorHelperTests.swift index 1cb68c7..5c866f7 100644 --- a/Tests/NanoViewControllerControllerTests/CoordinatorHelperTests.swift +++ b/Tests/NanoViewControllerControllerTests/CoordinatorHelperTests.swift @@ -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 @testable import NanoViewControllerController diff --git a/Tests/NanoViewControllerControllerTests/NanoViewControllerBehaviorTests.swift b/Tests/NanoViewControllerControllerTests/NanoViewControllerBehaviorTests.swift index 6d8bca2..e76004b 100644 --- a/Tests/NanoViewControllerControllerTests/NanoViewControllerBehaviorTests.swift +++ b/Tests/NanoViewControllerControllerTests/NanoViewControllerBehaviorTests.swift @@ -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 @testable import NanoViewControllerController diff --git a/Tests/NanoViewControllerControllerTests/NanoViewControllerConfigTests.swift b/Tests/NanoViewControllerControllerTests/NanoViewControllerConfigTests.swift index 9f5d0e3..2e3c72e 100644 --- a/Tests/NanoViewControllerControllerTests/NanoViewControllerConfigTests.swift +++ b/Tests/NanoViewControllerControllerTests/NanoViewControllerConfigTests.swift @@ -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 @testable import NanoViewControllerController diff --git a/Tests/NanoViewControllerControllerTests/NavigationBarAndToastTests.swift b/Tests/NanoViewControllerControllerTests/NavigationBarAndToastTests.swift index 09f7c49..a2bb8c0 100644 --- a/Tests/NanoViewControllerControllerTests/NavigationBarAndToastTests.swift +++ b/Tests/NanoViewControllerControllerTests/NavigationBarAndToastTests.swift @@ -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 @testable import NanoViewControllerController import NanoViewControllerCore diff --git a/Tests/NanoViewControllerControllerTests/NavigationHandlerSPITests.swift b/Tests/NanoViewControllerControllerTests/NavigationHandlerSPITests.swift index 962ddb4..44cc8fe 100644 --- a/Tests/NanoViewControllerControllerTests/NavigationHandlerSPITests.swift +++ b/Tests/NanoViewControllerControllerTests/NavigationHandlerSPITests.swift @@ -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 @_spi(Testing) @testable import NanoViewControllerController @@ -101,6 +101,74 @@ final class NavigationHandlerSPITests: XCTestCase { ) } + // MARK: - Mutual exclusivity of the two SPI hooks + + func test_resubscribingModalAfterPush_clearsThePushHandler() throws { + // Arrange — wire up a scene through the push helper first, capturing + // both push and modal handler invocations so we can assert that only + // the most-recent subscription receives emissions. + let coordinator = TestCoordinator(navigationController: UINavigationController()) + let viewModel = SPITestViewModel() + var pushRouted = [SPITestStep]() + var modalRouted = [SPITestStep]() + + coordinator.push(scene: SPITestScene.self, viewModel: viewModel, animated: false) { + pushRouted.append($0) + } + let scene = try XCTUnwrap(coordinator.navigationController.viewControllers.last as? SPITestScene) + XCTAssertNotNil(scene.navigationHandler) + XCTAssertNil(scene.modalNavigationHandler) + + // Act — re-subscribe the same instance through the modal helper. + coordinator.subscribeToModalNavigation(of: scene) { step, _ in + modalRouted.append(step) + } + + // Assert — SPI hook properties flipped. + XCTAssertNotNil(scene.modalNavigationHandler) + XCTAssertNil(scene.navigationHandler) + + // Assert — Combine route also flipped. Emitting through the VM should + // hit only the latest subscription, not both. (Without cancelling the + // prior sink, this would land in `pushRouted` as well.) + viewModel.trigger.send(.alpha) + pumpMainRunLoop() + XCTAssertEqual(pushRouted, [], "previous push subscription must be cancelled on re-subscribe") + XCTAssertEqual(modalRouted, [.alpha]) + } + + func test_resubscribingPushAfterModal_clearsTheModalHandler() throws { + // Arrange — wire up via modal first. + let nav = ModalPresentCapturingNavigationController() + let coordinator = TestCoordinator(navigationController: nav) + let viewModel = SPITestViewModel() + var modalRouted = [SPITestStep]() + var pushRouted = [SPITestStep]() + + coordinator.modallyPresent(scene: SPITestScene.self, viewModel: viewModel, animated: false) { step, _ in + modalRouted.append(step) + } + let presented = try XCTUnwrap(nav.presentedViewControllerCapture as? UINavigationController) + let scene = try XCTUnwrap(presented.viewControllers.first as? SPITestScene) + XCTAssertNotNil(scene.modalNavigationHandler) + XCTAssertNil(scene.navigationHandler) + + // Act — re-subscribe the same instance through the push helper. + coordinator.subscribeToNavigation(of: scene) { + pushRouted.append($0) + } + + // Assert — SPI hook properties flipped. + XCTAssertNotNil(scene.navigationHandler) + XCTAssertNil(scene.modalNavigationHandler) + + // Assert — Combine route also flipped. + viewModel.trigger.send(.alpha) + pumpMainRunLoop() + XCTAssertEqual(modalRouted, [], "previous modal subscription must be cancelled on re-subscribe") + XCTAssertEqual(pushRouted, [.alpha]) + } + func test_modalNavigationHandler_dismissForwardsAnimatedFlagAndCompletion() { // Arrange let nav = ModalPresentCapturingNavigationController() diff --git a/Tests/NanoViewControllerControllerTests/TestSupport.swift b/Tests/NanoViewControllerControllerTests/TestSupport.swift index 4be297a..553ee5a 100644 --- a/Tests/NanoViewControllerControllerTests/TestSupport.swift +++ b/Tests/NanoViewControllerControllerTests/TestSupport.swift @@ -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 diff --git a/Tests/NanoViewControllerCoreTests/AbstractTargetTests.swift b/Tests/NanoViewControllerCoreTests/AbstractTargetTests.swift index 90a71ab..b2a2741 100644 --- a/Tests/NanoViewControllerCoreTests/AbstractTargetTests.swift +++ b/Tests/NanoViewControllerCoreTests/AbstractTargetTests.swift @@ -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 @testable import NanoViewControllerCore diff --git a/Tests/NanoViewControllerCoreTests/ActivityIndicatorTests.swift b/Tests/NanoViewControllerCoreTests/ActivityIndicatorTests.swift index 22f7e5d..37f5204 100644 --- a/Tests/NanoViewControllerCoreTests/ActivityIndicatorTests.swift +++ b/Tests/NanoViewControllerCoreTests/ActivityIndicatorTests.swift @@ -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 @testable import NanoViewControllerCore diff --git a/Tests/NanoViewControllerCoreTests/BindingsBuilderTests.swift b/Tests/NanoViewControllerCoreTests/BindingsBuilderTests.swift index e80597e..fa62b58 100644 --- a/Tests/NanoViewControllerCoreTests/BindingsBuilderTests.swift +++ b/Tests/NanoViewControllerCoreTests/BindingsBuilderTests.swift @@ -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 @testable import NanoViewControllerCore diff --git a/Tests/NanoViewControllerCoreTests/ErrorTrackerCompactMapTests.swift b/Tests/NanoViewControllerCoreTests/ErrorTrackerCompactMapTests.swift index 5314b37..dd2997b 100644 --- a/Tests/NanoViewControllerCoreTests/ErrorTrackerCompactMapTests.swift +++ b/Tests/NanoViewControllerCoreTests/ErrorTrackerCompactMapTests.swift @@ -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 @testable import NanoViewControllerCore diff --git a/Tests/NanoViewControllerCoreTests/ErrorTrackerTests.swift b/Tests/NanoViewControllerCoreTests/ErrorTrackerTests.swift index 77316af..3af32a1 100644 --- a/Tests/NanoViewControllerCoreTests/ErrorTrackerTests.swift +++ b/Tests/NanoViewControllerCoreTests/ErrorTrackerTests.swift @@ -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 @testable import NanoViewControllerCore diff --git a/Tests/NanoViewControllerCoreTests/NanoViewControllerCoreSmokeTests.swift b/Tests/NanoViewControllerCoreTests/NanoViewControllerCoreSmokeTests.swift index 88fdd95..2c444b5 100644 --- a/Tests/NanoViewControllerCoreTests/NanoViewControllerCoreSmokeTests.swift +++ b/Tests/NanoViewControllerCoreTests/NanoViewControllerCoreSmokeTests.swift @@ -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 @testable import NanoViewControllerCore diff --git a/Tests/NanoViewControllerDIPrimitivesTests/ClockTests.swift b/Tests/NanoViewControllerDIPrimitivesTests/ClockTests.swift index a74aa5b..dee2989 100644 --- a/Tests/NanoViewControllerDIPrimitivesTests/ClockTests.swift +++ b/Tests/NanoViewControllerDIPrimitivesTests/ClockTests.swift @@ -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 @testable import NanoViewControllerDIPrimitives import XCTest diff --git a/Tests/NanoViewControllerDIPrimitivesTests/DateProviderTests.swift b/Tests/NanoViewControllerDIPrimitivesTests/DateProviderTests.swift index dc3f6e4..cfea8c7 100644 --- a/Tests/NanoViewControllerDIPrimitivesTests/DateProviderTests.swift +++ b/Tests/NanoViewControllerDIPrimitivesTests/DateProviderTests.swift @@ -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 @testable import NanoViewControllerDIPrimitives import XCTest diff --git a/Tests/NanoViewControllerDIPrimitivesTests/HapticFeedbackTests.swift b/Tests/NanoViewControllerDIPrimitivesTests/HapticFeedbackTests.swift index 2006d2f..e193735 100644 --- a/Tests/NanoViewControllerDIPrimitivesTests/HapticFeedbackTests.swift +++ b/Tests/NanoViewControllerDIPrimitivesTests/HapticFeedbackTests.swift @@ -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 @testable import NanoViewControllerDIPrimitives import UIKit diff --git a/Tests/NanoViewControllerDIPrimitivesTests/MainSchedulerTests.swift b/Tests/NanoViewControllerDIPrimitivesTests/MainSchedulerTests.swift index 749cd68..e6021d6 100644 --- a/Tests/NanoViewControllerDIPrimitivesTests/MainSchedulerTests.swift +++ b/Tests/NanoViewControllerDIPrimitivesTests/MainSchedulerTests.swift @@ -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 @testable import NanoViewControllerDIPrimitives import XCTest diff --git a/Tests/NanoViewControllerDIPrimitivesTests/PasteboardTests.swift b/Tests/NanoViewControllerDIPrimitivesTests/PasteboardTests.swift index 54c3679..aa8a82b 100644 --- a/Tests/NanoViewControllerDIPrimitivesTests/PasteboardTests.swift +++ b/Tests/NanoViewControllerDIPrimitivesTests/PasteboardTests.swift @@ -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 @testable import NanoViewControllerDIPrimitives diff --git a/justfile b/justfile index 5b37f32..dc50530 100644 --- a/justfile +++ b/justfile @@ -11,7 +11,7 @@ result_dir := ".build" result := result_dir + "/TestResults.xcresult" cov_json := result_dir + "/coverage.json" sim_device := env_var_or_default("SIM_DEVICE", "iPhone 17") -sim_os := env_var_or_default("SIM_OS", "26.1") +sim_os := env_var_or_default("SIM_OS", "26.2") # Keep in sync with .github/workflows/ci.yml to ensure local and CI use # the same Apple Silicon simulator destination.