0

所以事情是这样的,我要声明一个这样的属性:

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总是会被赋值为“BAD”,而实际上 myguard let是成功的。我该如何解决?

4

1 回答 1

2

问题是每次访问变量时都会创建一个新UILabel变量aNameLabel(每次访问时都会运行一个计算属性函数)。大概您正在为此视图的超级视图做同样的事情(当您someViewsomeView.addSubview()上面的示例中访问时)。如果是这样,这就是为什么没有共同的超级视图并且您正在崩溃的原因。

您应该只为视图控制器使用的每个实例创建一个实例UIView,因此如您所见,将变量创建为常量一种很好的方法,或者您可以使用闭包初始化器模式,如下所示:

var aNameLabel: UILabel = {
    return UILabel(...)
}()

请注意上例中右大括号后面的括号。因为它是一个闭包初始化器,它只会像let常量一样被调用一次。

UIViewcreated with通常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
    }
}
于 2016-08-13T15:45:02.390 回答