简体   繁体   中英

Is it ok to call closures in UIKit UIViewController from Hosted SwiftUI View?

I'm hosting ContentView in WrapperViewController like this:

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?()
        }
    }
}

I'm calling buttonTapped in the WrapperViewController from ContentView , but is this fine? "tapped button" is getting printed, but I read this article that said

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. }

So should I use a closure here? Or am I supposed to do something else?

We cannot use [weak myCar] as myCar is a value type.

In the example from the article, myCar is a struct .

However, in your code:

contentView.buttonTapped = { [weak self] in
    self?.tappedButton()
}

self is a UIViewController which is a class (and a reference type).

Your use of [weak self] is perfectly fine: the closure will keep a weak reference to the UIViewController and when you tap a button, the tappedButton() function will be called. Which is probably what you expect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM