How to pass a local function to another object during init?

前端 未结 3 1293
悲&欢浪女
悲&欢浪女 2021-01-29 11:09

How to pass a local function to another object during init?

I did the below, but got \'self\' captured by a closure before all members were initialized

<
相关标签:
3条回答
  • 2021-01-29 11:21

    First, your property drawViewWrapper seems to be useless here since you can access it later with self.rootView and second, you should use [unowned self] to avoid capturing 'self' and creating a weak reference to it instead (and then avoid a retain-cycle).

    So I would do something like this instead:

    class ContextViewController: UIHostingController<ContentView> {
        
        init(drawView: CustomDrawView) {
            let drawViewWrapper = ContentView(
                drawView: drawView,
                dismiss: { [unowned self] in
                    self.dismiss(animated: true)
                })
            super.init(rootView: drawViewWrapper)
        }
    
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    

    And then if you need to access it later, you can simply use self.rootView.

    0 讨论(0)
  • 2021-01-29 11:28

    You have to call super.init() before:

    class ContextViewController: UIHostingController<ContentView> {
    
        let drawViewWrapper: ContentView?
        
        init(drawView: CustomDrawView) {
            super.init(rootView: self.drawViewWrapper)
            self.drawViewWrapper = ContentView(
                drawView: drawView,
                dismiss: { self.dismiss(animated: true) })
        }
    
    }
    
    0 讨论(0)
  • 2021-01-29 11:38

    if it's an option for you I'd suggest making the dismiss block not part of the init but rather an optional var on the ContentView.

    My solution would look kind of like:

    ContentView

    class ContentView: UIView {
        var dismiss: (() -> Void)?
        
        init(drawView: UIView) {
            super.init(frame: .zero)
        }
        
        ...
    }
    

    You could also indicate the dismiss block will always be there by replacing the ? with an ! (var dismiss: (() -> Void)!) so you don't have to unwrap it when calling but I wouldn't suggest that as it's not compile time safe and so not what you really want.

    ContextViewController

    class ContextViewController: UIHostingController<ContentView> {
    
        let drawViewWrapper: ContentView
        
        lazy var selfDismiss: () -> Void = { [unowned self] in
            self.dismiss(animated: true)
        }
        
        init(drawView: CustomDrawView) {
            self.drawViewWrapper = ContentView(drawView: drawView)
            super.init(rootView: self.drawViewWrapper)
            self.drawViewWrapper.dismiss = selfDismiss
        }
        
        ...
    }
    
    0 讨论(0)
提交回复
热议问题