This commit is contained in:
Kylmakalle 2024-09-28 02:45:22 +03:00
parent 5cd2439859
commit 60a5a29b70

View File

@ -30,26 +30,87 @@ public class SwiftUIViewControllerInteraction {
public protocol SwiftUIView: View {
var controllerInteraction: SwiftUIViewControllerInteraction? { get set }
var layout: ContainerViewLayout { get set }
var navigationHeight: CGFloat { get set }
}
struct MySwiftUIView: SwiftUIView {
var controllerInteraction: SwiftUIViewControllerInteraction?
@Binding var navigationHeight: CGFloat
var num: Int64
var body: some View {
Color.orange
.padding(.top, 2.0 * (_navigationHeight ?? 0))
}
}
struct CustomButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
.frame(height: 44) // Set a fixed height for all buttons
}
}
private final class SwiftUIViewControllerNode<Content: SwiftUIView>: ASDisplayNode {
private let hostingController: UIHostingController<Content>
private let swiftUINode: ASDisplayNode
private var isDismissed = false
private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)?
init(swiftUIView: Content) {
self.hostingController = UIHostingController(rootView: swiftUIView)
self.swiftUINode = ASDisplayNode { [weak hostingController] in
hostingController?.view ?? UIView()
}
super.init()
addSubnode(self.swiftUINode)
// For debugging
self.backgroundColor = .red.withAlphaComponent(0.3)
hostingController.view.backgroundColor = .blue.withAlphaComponent(0.3)
}
override func didLoad() {
super.didLoad()
// Defer the setup to ensure we have a valid view controller hierarchy
DispatchQueue.main.async { [weak self] in
self?.setupHostingController()
}
}
private func setupHostingController() {
guard let viewController = findViewController() else {
assert(true, "Error: Could not find a parent view controller")
return
}
viewController.addChild(hostingController)
view.addSubview(hostingController.view)
hostingController.didMove(toParent: viewController)
// Ensure the hosting controller's view has a size
hostingController.view.frame = self.bounds
print("SwiftUIViewControllerNode setup - Node frame: \(self.frame), Hosting view frame: \(hostingController.view.frame)")
}
private func findViewController() -> UIViewController? {
var responder: UIResponder? = self.view
while let nextResponder = responder?.next {
if let viewController = nextResponder as? UIViewController {
return viewController
}
responder = nextResponder
}
return nil
}
override func layout() {
super.layout()
hostingController.view.frame = self.bounds
print("SwiftUIViewControllerNode layout - Node frame: \(self.frame), Hosting view frame: \(hostingController.view.frame)")
}
func containerLayoutUpdated(
@ -63,16 +124,21 @@ private final class SwiftUIViewControllerNode<Content: SwiftUIView>: ASDisplayNo
self.validLayout = (layout, navigationHeight)
transition.updateFrame(
node: self.swiftUINode,
frame: CGRect(
origin: CGPoint(x: 0, y: navigationHeight),
size: CGSize(
width: layout.size.width,
height: layout.size.height - navigationHeight - layout.safeInsets.top
)
let frame = CGRect(
origin: CGPoint(x: 0, y: 0),
size: CGSize(
width: layout.size.width,
height: layout.size.height
)
)
transition.updateFrame(node: self, frame: frame)
print("containerLayoutUpdated - New frame: \(frame)")
// Ensure hosting controller view is updated
hostingController.view.frame = bounds
hostingController.rootView.navigationHeight = navigationHeight
}
func animateOut(completion: @escaping () -> Void) {
@ -83,16 +149,31 @@ private final class SwiftUIViewControllerNode<Content: SwiftUIView>: ASDisplayNo
self.isDismissed = true
let transition: ContainedViewLayoutTransition = .animated(duration: 0.4, curve: .spring)
transition.updateFrame(
node: self.swiftUINode,
frame: CGRect(
origin: CGPoint(x: 0, y: navigationHeight),
size: CGSize(
width: layout.size.width,
height: layout.size.height - navigationHeight - layout.safeInsets.top
)
let frame = CGRect(
origin: CGPoint(x: 0, y: 0),
size: CGSize(
width: layout.size.width,
height: layout.size.height
)
)
transition.updateFrame(node: self, frame: frame, completion: { _ in
completion()
})
hostingController.rootView.navigationHeight = navigationHeight
}
override func didEnterHierarchy() {
super.didEnterHierarchy()
print("SwiftUIViewControllerNode entered hierarchy")
}
override func didExitHierarchy() {
super.didExitHierarchy()
hostingController.willMove(toParent: nil)
hostingController.view.removeFromSuperview()
hostingController.removeFromParent()
print("SwiftUIViewControllerNode exited hierarchy")
}
}
@ -167,31 +248,6 @@ public final class SwiftUIViewController<Content: SwiftUIView>: ViewController {
}
}
struct MySwiftUIView: SwiftUIView {
@State var layout: ContainerViewLayout
@State var navigationHeight: CGFloat
var controllerInteraction: SwiftUIViewControllerInteraction?
var num: Int64
var body: some View {
Color.orange
.ignoresSafeArea()
}
}
struct CustomButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
.frame(height: 44) // Set a fixed height for all buttons
}
}
func mySwiftUIViewController(_ num: Int64) -> ViewController {
let controller = SwiftUIViewController(MySwiftUIView(num: num))