From 8750c34cc2bc539b719fedf4247b160aca07b7a8 Mon Sep 17 00:00:00 2001 From: maximkrouk Date: Fri, 22 Dec 2023 01:47:49 +0100 Subject: [PATCH] feat: CustomHostingController - Add CustomHostingController - Use @_spi attributes for CustomView/Window loading --- .../CusomCocoaViewController.swift | 8 +- .../CustomCocoaWindowController.swift | 8 +- .../Controllers/CustomHostingController.swift | 216 ++++++++++++++++++ .../CustomNavigationController.swift | 4 + .../Controllers/CustomTabBarController.swift | 2 + Sources/CocoaExtensions/Macros.swift | 6 +- 6 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 Sources/CocoaExtensions/Custom/Controllers/CustomHostingController.swift diff --git a/Sources/CocoaExtensions/Custom/Controllers/CusomCocoaViewController.swift b/Sources/CocoaExtensions/Custom/Controllers/CusomCocoaViewController.swift index 559c3e1..d97173d 100644 --- a/Sources/CocoaExtensions/Custom/Controllers/CusomCocoaViewController.swift +++ b/Sources/CocoaExtensions/Custom/Controllers/CusomCocoaViewController.swift @@ -41,10 +41,13 @@ open class CustomCocoaViewController: @Handler public var onViewDidLayout + #if !canImport(CocoaExtensionsMacros) open override func loadView() { guard !tryLoadCustomContentView() else { return } super.loadView() } + #endif + open override func viewDidLoad() { super.viewDidLoad() @@ -88,11 +91,13 @@ open class CustomCocoaViewController: _onDismiss() } + /// Use `override _init` instead of overriding this initializer public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) self._init() } + /// Use `override _init` instead of overriding this initializer public required init?(coder: NSCoder) { super.init(coder: coder) self._init() @@ -106,7 +111,6 @@ open class CustomCocoaViewController: CocoaViewController, CustomCocoaViewControllerProtocol { - private(set) open var isVisible = false @Handler @@ -133,10 +137,12 @@ open class CustomCocoaViewController: @Handler public var onViewDidLayout + #if !canImport(CocoaExtensionsMacros) open override func loadView() { guard !tryLoadCustomContentView() else { return } super.loadView() } + #endif open override func viewDidLoad() { super.viewDidLoad() diff --git a/Sources/CocoaExtensions/Custom/Controllers/CustomCocoaWindowController.swift b/Sources/CocoaExtensions/Custom/Controllers/CustomCocoaWindowController.swift index a0704af..17b180d 100644 --- a/Sources/CocoaExtensions/Custom/Controllers/CustomCocoaWindowController.swift +++ b/Sources/CocoaExtensions/Custom/Controllers/CustomCocoaWindowController.swift @@ -12,22 +12,26 @@ open class CustomCocoaWindowController: @Handler public var onWindowDidLoad + /// Use `override _init` instead of overriding this initializer public override init(window: CocoaWindow?) { super.init(window: window) self._init() } + /// Use `override _init` instead of overriding this initializer public required init?(coder: NSCoder) { super.init(coder: coder) self._init() } - open func _init() {} - + #if !canImport(CocoaExtensionsMacros) open override func loadWindow() { guard !tryLoadCustomWindow() else { return } super.loadWindow() } + #endif + + open func _init() {} open override func windowWillLoad() { super.windowWillLoad() diff --git a/Sources/CocoaExtensions/Custom/Controllers/CustomHostingController.swift b/Sources/CocoaExtensions/Custom/Controllers/CustomHostingController.swift new file mode 100644 index 0000000..4a8f5bd --- /dev/null +++ b/Sources/CocoaExtensions/Custom/Controllers/CustomHostingController.swift @@ -0,0 +1,216 @@ +#if canImport(SwiftUI) +import DeclarativeConfiguration +import CocoaAliases +import SwiftUI + +extension CocoaHostingController where Content: ExpressibleByNilLiteral { + public convenience init() { + self.init(rootView: nil) + } +} + +#if canImport(UIKit) && !os(watchOS) + +extension CustomHostingController: NavigationControllerDynamicOverridable {} + +open class CustomHostingController: + CocoaHostingController, + CustomCocoaViewControllerProtocol +{ + private(set) open var isVisible = false + + @OptionalDataSource + public var overrideNavigationController + + override open var navigationController: UINavigationController? { + _overrideNavigationController() ?? super.navigationController + } + + @Handler + public var onDismiss + + @Handler + public var onViewDidLoad + + @Handler + public var onViewWillAppear + + @Handler + public var onViewDidAppear + + @Handler + public var onViewWillDisappear + + @Handler + public var onViewDidDisappear + + @Handler + public var onViewWillLayout + + @Handler + public var onViewDidLayout + + open override func viewDidLoad() { + super.viewDidLoad() + _onViewDidLoad() + } + + open override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + _onViewWillAppear() + } + + open override func viewDidAppear(_ animated: Bool) { + isVisible = true + super.viewDidAppear(animated) + _onViewDidAppear() + } + + open override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + _onViewWillDisappear() + } + + open override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + _onViewDidDisappear() + isVisible = false + } + + open override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + _onViewWillLayout() + } + + open override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + _onViewDidLayout() + } + + open override func dismiss(animated: Bool, completion: (() -> Void)? = nil) { + super.dismiss(animated: animated, completion: completion) + _onDismiss() + } + + /// Use `override _init` instead of overriding this initializer + public override init(rootView: Content) { + super.init(rootView: rootView) + self._init() + } + + /// Use `override _init` instead of overriding this initializer + public override init?(coder: NSCoder, rootView: Content) { + super.init(coder: coder, rootView: rootView) + self._init() + } + + /// Use `override _init` instead of overriding this initializer + public required init?(coder: NSCoder) { + super.init(coder: coder) + self._init() + } + + /// Only for `override` purposes, do not call directly + open func _init() {} +} + +#elseif canImport(AppKit) +import DeclarativeConfiguration +import CocoaAliases +import SwiftUI + +open class CustomHostingController: + CocoaHostingController, + CustomCocoaViewControllerProtocol +{ + private(set) open var isVisible = false + + @Handler + public var onDismiss + + @Handler + public var onViewDidLoad + + @Handler + public var onViewWillAppear + + @Handler + public var onViewDidAppear + + @Handler + public var onViewWillDisappear + + @Handler + public var onViewDidDisappear + + @Handler + public var onViewWillLayout + + @Handler + public var onViewDidLayout + + open override func viewDidLoad() { + super.viewDidLoad() + _onViewDidLoad() + } + + open override func viewWillAppear() { + super.viewWillAppear() + _onViewWillAppear() + } + + open override func viewDidAppear() { + isVisible = true + super.viewDidAppear() + _onViewDidAppear() + } + + open override func viewWillDisappear() { + super.viewWillDisappear() + _onViewWillDisappear() + } + + open override func viewDidDisappear() { + super.viewDidDisappear() + _onViewDidDisappear() + isVisible = false + } + + open override func viewWillLayout() { + super.viewWillLayout() + _onViewWillLayout() + } + + open override func viewDidLayout() { + super.viewDidLayout() + _onViewDidLayout() + } + + open override func dismiss(_ sender: Any?) { + super.dismiss(sender) + self._onDismiss() + } + + /// Use `override _init` instead of overriding this initializer + public override init(rootView: Content) { + super.init(rootView: rootView) + self._init() + } + + /// Use `override _init` instead of overriding this initializer + public override init?(coder: NSCoder, rootView: Content) { + super.init(coder: coder, rootView: rootView) + self._init() + } + + /// Use `override _init` instead of overriding this initializer + public required init?(coder: NSCoder) { + super.init(coder: coder) + self._init() + } + + /// Only for `override` purposes, do not call directly + open func _init() {} +} +#endif +#endif diff --git a/Sources/CocoaExtensions/Custom/Controllers/CustomNavigationController.swift b/Sources/CocoaExtensions/Custom/Controllers/CustomNavigationController.swift index 819e1bf..0898099 100644 --- a/Sources/CocoaExtensions/Custom/Controllers/CustomNavigationController.swift +++ b/Sources/CocoaExtensions/Custom/Controllers/CustomNavigationController.swift @@ -83,21 +83,25 @@ open class CustomNavigationController: _onDismiss() } + /// Use `override _init` instead of overriding this initializer public override init(rootViewController: UIViewController) { super.init(rootViewController: rootViewController) self._init() } + /// Use `override _init` instead of overriding this initializer public override init(navigationBarClass: AnyClass?, toolbarClass: AnyClass?) { super.init(navigationBarClass: navigationBarClass, toolbarClass: toolbarClass) self._init() } + /// Use `override _init` instead of overriding this initializer public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) self._init() } + /// Use `override _init` instead of overriding this initializer public required init?(coder: NSCoder) { super.init(coder: coder) self._init() diff --git a/Sources/CocoaExtensions/Custom/Controllers/CustomTabBarController.swift b/Sources/CocoaExtensions/Custom/Controllers/CustomTabBarController.swift index 7395db1..167f8c8 100644 --- a/Sources/CocoaExtensions/Custom/Controllers/CustomTabBarController.swift +++ b/Sources/CocoaExtensions/Custom/Controllers/CustomTabBarController.swift @@ -83,11 +83,13 @@ open class CustomTabBarController: _onDismiss() } + /// Use `override _init` instead of overriding this initializer public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) self._init() } + /// Use `override _init` instead of overriding this initializer public required init?(coder: NSCoder) { super.init(coder: coder) self._init() diff --git a/Sources/CocoaExtensions/Macros.swift b/Sources/CocoaExtensions/Macros.swift index 770212c..d83666d 100644 --- a/Sources/CocoaExtensions/Macros.swift +++ b/Sources/CocoaExtensions/Macros.swift @@ -137,8 +137,9 @@ public struct CustomView: CustomReflectable { extension CocoaViewController { /// Loads `@CustomView var contentView` to the controller /// - Returns: `true` if loading succeed, `false` if failed + @_spi(Internals) @discardableResult - func tryLoadCustomContentView() -> Bool { + public func tryLoadCustomContentView() -> Bool { let selfMirror = Mirror(reflecting: self) guard let _contentView = selfMirror.children @@ -228,8 +229,9 @@ public struct CustomWindow: CustomReflectable { } extension NSWindowController { + @_spi(Internals) @discardableResult - func tryLoadCustomWindow() -> Bool { + public func tryLoadCustomWindow() -> Bool { guard let _managedWindow = Mirror(reflecting: self).children.first(where: { $0.label == "_managedWindow" })?.value, let loadWindow = Mirror(reflecting: _managedWindow).children.first(where: { $0.label == "loadWindow" })?.value,