【问题标题】:SwiftUI Button doesn't work in UIHostingControllerSwiftUI 按钮在 UIHostingController 中不起作用
【发布时间】:2022-11-05 01:15:07
【问题描述】:

我有一个使用 UIHostingController 嵌入现有 UIViewController 的 SwiftUI 视图。 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:) 而不是按钮,但这也不起作用。为了让事情变得更奇怪,我可以添加一个 ScrollView 作为我的 SwiftUI 和滚动工作的子视图。为什么我的按钮不起作用?

【问题讨论】:

    标签: ios swiftui uikit


    【解决方案1】:

    显然问题是父 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
    }
    

    【讨论】:

    • 供您参考,这不是问题“所有 SwiftUI 轻按手势”...您的转换代码更改了视觉外观但不是视图层次结构。因此,此时,您的按钮超出了其父视图的范围,您无法再与它进行交互。无论 UIKit 还是 SwiftUI 都是如此。因此,正如您所发现的,您想要更改视图的框架,而不是改变其外观。
    • @DonMag 我认为您误解了我的代码。视图被渲染到屏幕外,然后使用transform 动画到屏幕上。在包含 self.view.transform = CGAffineTransform.identity 的动画之后,视图的渲染位置恢复正常,但 SwiftUI 按钮的点击手势识别器没有。
    • 如果您提供minimal reproducible example 会有所帮助,以便我们确认您的经历。从表面上看,应用变换然后将其重置为.identity不应该影响点击手势。
    【解决方案2】:

    有类似的问题,但在 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
      }
    
    // ...
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-30
      • 2020-04-01
      • 2020-04-23
      • 1970-01-01
      • 1970-01-01
      • 2019-11-11
      • 2021-07-23
      • 1970-01-01
      相关资源
      最近更新 更多