SwiftUI 按钮在 UIHostingController 中不起作用

发布于 2025-01-11 13:42:09 字数 752 浏览 1 评论 0原文

我有一个 SwiftUI 视图,我使用 UIHostingController 将其嵌入到现有的 UIViewController 中。 SwiftUI 视图很简单,事实上我可以将其简化为以下代码并重现问题:

let hostingController = UIHostingController(rootView: Button {
   print("tapped")
} label {
   Text("Tap")
}

HostingController 作为子项添加到我现有的视图控制器中,如下所示:

override func viewDidLoad() {
   super.viewDidLoad()
   view.addSubview(hostingController.view)
   // Code to set up autolayout constraints omitted.
   addChild(hostingController)
   hostingController.didMove(toParent: self)
}

该按钮在画布预览中可点击,但在模拟器中不可点击或在真实设备上。没有手势识别器或其他视图覆盖 UIHostingController 的视图。我尝试使用 .onTapGesture(perform:) 而不是 Button,但这也不起作用。为了让事情变得更奇怪,我可以添加一个 ScrollView 作为我的 SwiftUI 和滚动工作的子视图。为什么我的按钮不起作用?

I have a SwiftUI View that I am embedding in an existing UIViewController using UIHostingController. The SwiftUI view is simple, in fact I can reduce it down to this code and reproduce the issue:

let hostingController = UIHostingController(rootView: Button {
   print("tapped")
} label {
   Text("Tap")
}

The hostingController is added to my existing view controller as a child like this:

override func viewDidLoad() {
   super.viewDidLoad()
   view.addSubview(hostingController.view)
   // Code to set up autolayout constraints omitted.
   addChild(hostingController)
   hostingController.didMove(toParent: self)
}

The button is tappable in the canvas preview, but not in the simulator or on a real device. There are no gesture recognizers or other views covering the UIHostingController's view. I tried using .onTapGesture(perform:) instead of a Button but that didn't work either. To make things weirder, I can add a ScrollView as a subview of my SwiftUI and scrolling works. Why won't my button work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

空城之時有危險 2025-01-18 13:42:10

显然,问题在于父 UIViewController 正在使用图层转换将自身动画到屏幕上。这种转变完全打破了所有 SwiftUI 的点击手势。当我更改图层转换代码以仅更改视图的框架时,一切正常。

有问题的转换代码如下所示:

view.transform = CGAffineTransform(translationX: -300, y: 0)

UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
    self.view.transform = CGAffineTransform.identity
}

我将其更改为如下所示:

view.frame.origin.x = view.frame.origin.x - 300

UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
    self.view.frame.origin.x = self.view.frame.origin.x + 300
}

Apparently the issue was that the parent UIViewController was using a layer transform to animate itself onto the screen. This transform totally broke all SwiftUI tap gestures. When I changed the layer transform code to just change the view's frame everything worked.

The offending transform code looked like this:

view.transform = CGAffineTransform(translationX: -300, y: 0)

UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
    self.view.transform = CGAffineTransform.identity
}

And I changed it to something like this:

view.frame.origin.x = view.frame.origin.x - 300

UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
    self.view.frame.origin.x = self.view.frame.origin.x + 300
}
奈何桥上唱咆哮 2025-01-18 13:42:10

有类似的问题,但在未完成 UIHostingConroller 的关闭后。这是我的解决方案:

class SomePresentationController: UIPresentationController { 

// ...

override func dismissalTransitionDidEnd(_ completed: Bool) {
    super.dismissalTransitionDidEnd(completed)

    // Magic, that fixes not working buttons and gestures after non finished dismiss
    presentedViewController.view.bounds.origin.y = 0.1
    presentedViewController.view.bounds.origin.y = .zero
  }

// ...

}

Had similar problem, but after not finished dismiss of UIHostingConroller. Here is my solution:

class SomePresentationController: UIPresentationController { 

// ...

override func dismissalTransitionDidEnd(_ completed: Bool) {
    super.dismissalTransitionDidEnd(completed)

    // Magic, that fixes not working buttons and gestures after non finished dismiss
    presentedViewController.view.bounds.origin.y = 0.1
    presentedViewController.view.bounds.origin.y = .zero
  }

// ...

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文