可以从 Hosted SwiftUI View 调用 UIKit UIViewController 中的闭包吗?
Is it ok to call closures in UIKit UIViewController from Hosted SwiftUI View?
我在 WrapperViewController
中托管 ContentView
是这样的:
class WrapperViewController: UIViewController {
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
self.view = UIView()
var contentView = ContentView()
contentView.buttonTapped = { [weak self] in
self?.tappedButton()
}
let contentViewController = UIHostingController(rootView: contentView)
self.addChild(contentViewController)
self.view.addSubview(contentViewController.view)
contentViewController.view.frame = view.bounds
contentViewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
contentViewController.didMove(toParent: self)
}
func tappedButton() {
print("tapped button")
}
}
struct ContentView: View {
var buttonTapped: (() -> Void)?
var body: some View {
Button("Tap me") {
buttonTapped?()
}
}
}
我正在从 ContentView
呼叫 WrapperViewController
中的 buttonTapped
,但这可以吗? “点击按钮”正在打印,但我读到这个 article 说
When you use closures in structs, the closure behaves as a reference type, and the problem starts there. The closures need to have a reference to the environment outside so that the environment can be modified when the closure body is executed.
struct Car {
var speed: Float = 0.0
var increaseSpeed: (() -> ())?
}
var myCar = Car()
myCar.increaseSpeed = {
myCar.speed += 30 // The retain cycle occurs here. We cannot use [weak myCar] as myCar is a value type.
}
那么我应该在这里使用闭包吗?还是我应该做点别的?
We cannot use [weak myCar] as myCar is a value type.
在文章的示例中,myCar
是一个 struct。
但是,在您的代码中:
contentView.buttonTapped = { [weak self] in
self?.tappedButton()
}
self
是一个 UIViewController
,它是一个 class(和引用类型)。
您对 [weak self]
的使用完全没问题:闭包将保持对 UIViewController 的弱引用,当您点击按钮时,将调用 tappedButton()
函数。这可能是您所期望的。
我在 WrapperViewController
中托管 ContentView
是这样的:
class WrapperViewController: UIViewController {
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
self.view = UIView()
var contentView = ContentView()
contentView.buttonTapped = { [weak self] in
self?.tappedButton()
}
let contentViewController = UIHostingController(rootView: contentView)
self.addChild(contentViewController)
self.view.addSubview(contentViewController.view)
contentViewController.view.frame = view.bounds
contentViewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
contentViewController.didMove(toParent: self)
}
func tappedButton() {
print("tapped button")
}
}
struct ContentView: View {
var buttonTapped: (() -> Void)?
var body: some View {
Button("Tap me") {
buttonTapped?()
}
}
}
我正在从 ContentView
呼叫 WrapperViewController
中的 buttonTapped
,但这可以吗? “点击按钮”正在打印,但我读到这个 article 说
When you use closures in structs, the closure behaves as a reference type, and the problem starts there. The closures need to have a reference to the environment outside so that the environment can be modified when the closure body is executed.
struct Car { var speed: Float = 0.0 var increaseSpeed: (() -> ())? } var myCar = Car() myCar.increaseSpeed = { myCar.speed += 30 // The retain cycle occurs here. We cannot use [weak myCar] as myCar is a value type. }
那么我应该在这里使用闭包吗?还是我应该做点别的?
We cannot use [weak myCar] as myCar is a value type.
在文章的示例中,myCar
是一个 struct。
但是,在您的代码中:
contentView.buttonTapped = { [weak self] in
self?.tappedButton()
}
self
是一个 UIViewController
,它是一个 class(和引用类型)。
您对 [weak self]
的使用完全没问题:闭包将保持对 UIViewController 的弱引用,当您点击按钮时,将调用 tappedButton()
函数。这可能是您所期望的。