2015-03-17 11 views
0

Я хочу настроить переменную с помощью let, чтобы ее не было необязательно, со временем не будет изменяться и не требует беспорядочного доступа для доступа каждый раз. Я знаю, что могу законно установить его, но только внутри одного из методов init. Проблема в том, что Swift требует переопределения инициализатора init(coder aDecoder: NSCoder). Однако у меня никогда не было приложения, которое когда-либо вызывало этот инициализатор. Его всегда вызывается инициализатор init(frame: CGRect). Так что, если бы мне не пришлось переопределять init(coder aDecoder: NSCoder), я бы просто сделал self.imageView = UIImageView.new() в init(frame: CGRect), и я бы это сделал, но компилятор жалуется, что он не установлен и в другом init. Я попытался сделать метод sharedInit(), который вызывается из обоих inits, но компилятор не позволяет мне устанавливать imageView, поскольку он читается только за пределами методов init. Как вы должны это сделать, не выполняя весь свой init дважды непосредственно в методах init?Как инициализировать переменную let с помощью общего метода init?

class SuperCoolView : UIView { 

    let imageView: UIImageView 

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

    override init(frame: CGRect) { 
     sharedInit() 
     super.init(frame: frame) 
    } 

    func sharedInit() { 
     self.imageView = UIImageView.new() 
     // Other similar shared init 
    } 

} 
+0

Swift 1.2 своего рода исправляет эту проблему (вы можете установить переменную LET где угодно, но, конечно, только один раз ..). – Ron

+0

Я делаю это в Xcode 6.3b3, поэтому я использую Swift 1.2, и я получаю ошибки. – jamone

+0

Возможный дубликат [Как реализовать два входа с одним контентом без дублирования кода в Swift?] (Http://stackoverflow.com/q/24023412/1445366). См. [Этот ответ в частности] (http://stackoverflow.com/a/24051352/1445366) - вы можете комбинировать инициализацию свойств на основе замыкания с помощью функции commonInit(). –

ответ

2

Я нашел this answer и мне понравился подход. Он исправил проблему и намного чище ИМХО. Внедряя init(coder aDecoder: NSCoder), мы обычно будем поддерживать внешний вид, что это представление может быть инициализировано из nib/раскадровки, когда оно не может.

class SuperCoolView : UIView { 

let imageView: UIImageView 

required init(coder aDecoder: NSCoder) { 
    fatalError("NSCoding not supported") 
} 

override init(frame: CGRect) { 
    self.imageView = UIImageView.new() 
    // Other stuff 
    super.init(frame: frame) 
} 

}

2

Просто используйте комбинацию отложенной инициализации и частного «установить», чтобы получить:

class SuperCoolView : UIView { 
    public private(set) lazy var imageView: UIImageView = { 
    // In practice, do more here. Access state in this instance. 
    // Or, include more computation. 
    UIImageView.new() 
    }() 

    // inits w/o setting imageView 
} 

«частный набор» делает это внешне идентичен let; lazy позволяет инициализировать значение на основе другого состояния в экземпляре SuperCoolView.

Обратите внимание, что если инициализация imageView и другие элементы не зависят от состояния в экземпляре, то вы можете избежать lazy и просто выполнить инициализацию с закрытием.

+0

Почему бы просто не использовать 'let imageView = UIImageView()'? Или инициализация 'let', основанная на закрытии, в ответе, с которым я связан? –

+0

Я обновил. Наши обновления пересекли. Да, если назначение не зависит от сложных вычислений или состояний в «SuperCoolView», вы можете просто назначить его. – GoZoner

+0

Я не поклонник использования закрытий в объявлениях свойств. Это делает чтение кода более сложным. Я предпочитаю, чтобы вершина swift-файла была просто общедоступными методами/свойствами с минимальными деталями реализации. Я действительно пропускаю файлы заголовков для этой цели. – jamone

Смежные вопросы