При использовании переменной Computed и Snapkit: нет общего суперпредставления между представлениями
Так вот, я объявляю свойство как это:
var aNameLabel: UILabel {
guard let foo = Applicant.sharedInstance.realName else {
return UILabel(text: "获取姓名失败", color: .whiteColor())
}
return UILabel(text: foo, color: .whiteColor())
}
И когда я пытаюсь добавить ограничение в aNameLabel после того, как я сделал someView.addSubView(aNameLabel)
приложение будет зависать каждый раз при добавлении ограничений и говорит No common superview between views
Однако, когда я изменяю переменную на постоянную let, вот так:
let aNameLabel = UILabel(text: "Allen", color: .whiteColor())
Ограничение будет добавлено без жалоб. Кто-нибудь может мне помочь с этим?
ОБНОВИТЬ
С помощью @par я изменил свой код так:
var aNameLabel: UILabel = {
guard let foo = Applicant.sharedInstance.realName else {
return UILabel(text: "BAD", color: .whiteColor())
}
return UILabel(text: foo, color: .whiteColor())
}()
А потом aNameLabel
всегда будет присвоено значение "ПЛОХО", в то время как на самом деле мой guard let
успешно. Как это исправить?
1 ответ
Проблема в том, что вы создаете новый UILabel
каждый раз, когда вы получаете доступ к aNameLabel
переменная (вычисляемая функция свойства запускается каждый раз, когда вы обращаетесь к ней). Предположительно, вы делаете то же самое для суперпредставления этого представления (когда вы someView
в someView.addSubview()
в вашем примере выше). Если так, вот почему нет общего супервизии и вы терпите крах.
Вы должны создать только один экземпляр каждого UIView
используется вашим контроллером представления, поэтому создание переменной в качестве константы, как вы показали, является отличным подходом, или вы можете использовать шаблон closure-initializer следующим образом:
var aNameLabel: UILabel = {
return UILabel(...)
}()
Обратите внимание, что в приведенном выше примере скобки после закрывающей скобки. Поскольку это инициализатор замыкания, он будет вызываться только один раз, как let
постоянная.
Часто UIView
создан с let
не подходит, потому что константные свойства должны быть инициализированы перед init()
возвращается, и если вы создаете представления в контроллере представления, у вас не будет возможности добавлять представления до loadView()
называется. В этом случае объявите UIView
s как неявно развернутые необязательные. Они будут установлены в nil
от init()
который соответствует требованию инициализации, тогда вы можете установить их на фактические представления позже, когда viewDidLoad()
называется, например:
class MyViewController: UIViewController {
var someSubview: UIView!
override func viewDidLoad() {
super.viewDidLoad()
someSubview = UIView()
view.addSubview(someSubview)
// now set constraints with SnapKit
}
}