Инициализируйте переменные экземпляра внутри функции экземпляра

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 ответа

Решение

Это происходит потому, что

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, верните желаемое значение, т.е.

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

Я думаю, что последний вариант является лучшим в этом случае.

Написать bind метод, как это. Это разрешит вашу ошибку.

func bind(footer: inout Footer!) {

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

Кажется, что inout думает Footer & Footer! разные. Либо обновите метод, как указано выше, либо измените объявление, как указано ниже.

var userFooter: Footer

Я не знаю точной причины, но ошибка, которую мы получаем, сбивает с толку.

Другие вопросы по тегам