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

我明白了:

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

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

4

2 回答 2

2

发生这种情况是因为

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 的语法使其隐式可选。

  • 强制解包:

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

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

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

于 2018-01-17T11:25:29.183 回答
0

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

func bind(footer: inout Footer!) {

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

似乎inout认为页脚和页脚!是不同的。如上所述的更新方法或如下所示的更改声明。

var userFooter: Footer

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

于 2018-01-17T11:03:13.170 回答