Свойство 'self.*' не инициализировано при вызове super.init

Я только что обновил свой xcode до 6.3.1. Проблема в том, что я получил это странное сообщение об ошибке, начиная с Swift 1.2. Я получил такое сообщение об ошибке

/Users/MNurdin/Documents/iOS/xxxxx/Library/SideBar.swift:32:15: Property 'self.originView' not initialized at super.init call

/Users/MNurdin/Documents/iOS/xxxxx/Library/SideBar.swift:38:20: Immutable value 'self.originView' may only be initialized once

по этому коду

let originView:UIView?

override init() {
        super.init() //error here

    }

    init(sourceView:UIView, menuItems:Array<String>){
        super.init() //error here
        originView = sourceView //error here

person Mohammad Nurdin    schedule 27.04.2015    source источник
comment
Это может быть вашей проблемой: stackoverflow.com/questions/29631800/   -  person ABakerSmith    schedule 27.04.2015


Ответы (3)


Вы должны инициализировать все свойства, прежде чем вызывать super.init в любом методе инициализации.

Итак, измените это, прежде чем вызывать super.init()

originView = sourceView //error here

Исключение:

  1. необязательное свойство
  2. свойство со значением по умолчанию
  3. ленивое свойство
person Community    schedule 27.04.2015
comment
Я уже инициализирую свое свойство. проверьте мой вопрос. Все равно ошибка. - person Mohammad Nurdin; 27.04.2015
comment
Этот ответ не совсем соответствует коду в вопросе. Проблема в этом случае не в том, где присваивается значение, проблема в том, что вы не можете объявить необязательное свойство с помощью let. - person John Montgomery; 31.05.2017

Сделайте свой originView обнуляемым,

var originView: UIView?. 

Если ваш originView не имеет значения NULL, вы должны указать значение по умолчанию перед вызовом

super.init().
person Nitheesh George    schedule 27.04.2015
comment
пусть originView:UIView!. вы объявили originView как константу, используя let. это должно быть вар. когда вы используете let, вам не будет разрешено снова изменить его значение, кроме как во время объявления. - person Nitheesh George; 27.04.2015
comment
вы правы, извините за мою ошибку. позвольте мне сначала попробовать. - person Mohammad Nurdin; 27.04.2015

Из книги Apple «Язык быстрого программирования»:

«Компилятор Swift выполняет четыре полезных действия safety-checks, чтобы убедиться, что двухэтапная инициализация выполнена без ошибок»

«Назначенный инициализатор должен убедиться, что все «свойства, введенные его классом, инициализированы, прежде чем он делегирует инициализатору суперкласса».

По сути, вы должны ensure that your instance variables are in a consistent state прежде чем что-либо делать, включая вызов методов.

class YourClass {
    var view: UIView
    init(view: UIView) {
        self.view = view
    }
}

хорошо, в вашем случае вы можете сделать его новым UIView:

let originView = UIView()

или сделайте его обнуляемым

let originView: UIView?

или вместо этого создайте ленивое свойство:

lazy var originView: UIView = {
    let view = UIView(frame: CGRect(x: 0, y: 0, width: 375, height: 200))
    // customize it
    return view
}()

при использовании ленивого создания экземпляров вы можете передать метод:

lazy var originView: UIView = self.createView()

func createView() -> UIView {
    let view = UIView(frame: CGRect(x: 0, y: 0, width: 375, height: 200))
        // customize it
        return view
}
person Oleh Zayats    schedule 18.03.2017
comment
Что является лучшей практикой? Использовать свойство nullable или lazy? - person Edgar; 02.05.2017
comment
@ Эдгар, это действительно зависит. Нет лучшего способа, вам нужно подумать, как должен вести себя ваш класс, какие состояния он должен иметь и в зависимости от информации, которую вы пишете в коде. Попробуйте сначала описать свои занятия на бумаге, а потом кодировать, скоро вы будете делать все в уме автоматически. - person Oleh Zayats; 02.05.2017