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

时间:2018-01-17 10:51:17

标签: swift inout

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

知道Footer是什么:

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

我明白了:

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

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

2 个答案:

答案 0 :(得分:1)

这是因为

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?)或使用Martin's syntax使其隐式可选。

  • 强行打开自己:

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

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

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

答案 1 :(得分:0)

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

func bind(footer: inout Footer!) {

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

似乎 inout 认为Footer&amp;页脚!是不同的。如上所述更新方法或更改下面给出的声明。

var userFooter: Footer

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