在实例函数中初始化实例变量

Initialize instance variables inside instance function

final class TestVC: UIViewController {
    var usersFooter: Footer!
    var groupsFooter: Footer!

    override func viewDidLoad() {
        super.viewDidLoad()

        bind(footer: &usersFooter)
    }

    func bind(footer: inout Footer) {

        footer = Footer(style: .autoFooter, height: 57) {
            // doing something
        }
    }
}

这就是页脚:

final class Footer: RefreshView {
    private var loader: MDCActivityIndicator!

    override public init(style: Style, height: CGFloat, action: @escaping () -> Void) {
        // initializing and doing something with loader

        super.init(style: style, height: height, action: action)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

我明白了:

无法将 'Footer' 类型的不可变值作为 inout 参数传递

如何在其函数中传递 TestVC 实例的页脚并能够对其进行初始化? 为什么页脚是不可变的(声明为 var)?

这样写bind方法。它将解决您的错误。

func bind(footer: inout Footer!) {

    footer = Footer(style: .autoFooter, height: 57) {
        // doing something
    }
}

It seems like inout thinks Footer & Footer! are different. Either update method as above or change declaration as given below.

var userFooter: Footer

我不知道确切原因,但我们得到的错误令人困惑。

这是因为

var someVar: Footer!

没有定义 Footer 类型的变量,而是隐式解包的 Optional<Footer> 类型的变量。代码:

var someFooter: Footer! 

bind(footer: &someFooter) 

在逻辑上等同于

var someFooter: Footer? 

guard let tempFooter = someFooter? else { fatalError() }
bind(footer: &tempFooter) 

如您所见,tempFooter 是一个 let,因此它不能作为 inout 变量传递,即使可以传递,结果也会被丢弃。

您可以通过以下三种方式之一解决此问题:

  • 使要绑定的参数成为可选参数,例如func bind(footer: inout Footer?) 或使用 使其隐式可选。

  • 自己强制展开:

    var unwrapped: Footer = someFooter
    bind(footer: unwrapped)
    someFooter = unwrapped
    
  • 重新设计API。您在 bind 函数中做的第一件事似乎是用新初始化的页脚覆盖旧页脚。所以不要使用 inout 参数,return 你想要的值,即

    func bind() -> Footer
    {
        var theFooter = Footer(...) { ... }
        // do stuff
    
        return theFooter
    }
    
    someFooter = bind()
    

在这种情况下,我认为最后一个选项是最好的。