var label: UILabel! 有什么区别?和 var label = UILabel( )?
What's the difference between var label: UILabel! and var label = UILabel( )?
我在写 Swift 时注意到,如果我在 ViewController
中将标签声明为 var label: UILabel!
或 var label = UILabel()
,然后在viewDidLoad
方法,它们在功能上似乎都是相同的。那么这两者有什么区别呢?
相关说明,当我声明 var label: UILabel!
时,我必须写 label = UILabel(frame:CGRectMake(...))
,但如果我使用 var label = UILabel()
,我必须写 label.frame = CGRectMake(...)
。这是因为 var label = UILabel()
既声明又实例化了 class 对象,而 var label: UILabel!
只是声明了一个类型的变量吗?我对这里实际发生的事情感到困惑。
提前致谢!
var label: UILabel!
声明您有一个可能为空的 UILabel 变量(可选),但您可以假装它不会访问它 - 通常这意味着它将是一个 IBOutlet,由界面故事板设置在您尝试使用标签之前加载。
var label = UILabel()
声明您有一个标签,该标签将始终包含一个标签,并且永远不会为零。它也在创建 class 实例时创建 UILabel 的实例,即使您说您为 viewDidLoad()
中的变量分配了不同的标签
访问权限没有区别,但这确实意味着无论您何时使用该变量,它都将保存一个真实值而不是 nil。
它们都是UILabel
.
类型的变量
我不确定为什么您不能使用 CGRect
构造函数将变量设置为新的 UILabel
,这应该是可能的。也许你曾经说过 let label = UILabel()
,这意味着它是一个不能保存新值的固定变量 - 所以你所能做的就是改变已经存在的变量的框架。
像你正在做的事情的最佳方法是将变量声明为可选:
var label : UILabel?
这使它成为一个真正的可选,并确保您不会意外编写错误地访问变量的代码,如果它从未被设置,或者在您分配 "real" 之前为您的第一个标签设置一个值viewDidLoad
方法中的 UILabel。访问有点不同,但并不难 - 要设置文本,您只需使用“?”如果实例已设置,可选择调用 属性 的语法:
label?.text = "fred"
你是对的。 UILabel()
调用 UILabel
无参数构造函数并将该对象引用分配给 label
变量。所以这是一个声明和一个初始化。
在构造函数的情况下,label
不是可选的,被推断为直接的 UILabel
类型,但在声明的情况下 label
是一个Optional
类型。这 !只是意味着它是一个可选的强制展开,所以当你将它用作一个值时,你不必输入 !;但是,如果您将其声明为强制展开并在其值为 nil
时使用它,您的程序将崩溃。
另请注意,您不能申报:
var label: UILabel
作为 class 成员 除非您在所有构造函数中初始化它,在(可能是隐式的)调用 super.init() 之前,因为它会抱怨没有初始值,因此它可能被引用时没有已知值——Swift 编译器会阻止这种情况。
我在写 Swift 时注意到,如果我在 ViewController
中将标签声明为 var label: UILabel!
或 var label = UILabel()
,然后在viewDidLoad
方法,它们在功能上似乎都是相同的。那么这两者有什么区别呢?
相关说明,当我声明 var label: UILabel!
时,我必须写 label = UILabel(frame:CGRectMake(...))
,但如果我使用 var label = UILabel()
,我必须写 label.frame = CGRectMake(...)
。这是因为 var label = UILabel()
既声明又实例化了 class 对象,而 var label: UILabel!
只是声明了一个类型的变量吗?我对这里实际发生的事情感到困惑。
提前致谢!
var label: UILabel!
声明您有一个可能为空的 UILabel 变量(可选),但您可以假装它不会访问它 - 通常这意味着它将是一个 IBOutlet,由界面故事板设置在您尝试使用标签之前加载。
var label = UILabel()
声明您有一个标签,该标签将始终包含一个标签,并且永远不会为零。它也在创建 class 实例时创建 UILabel 的实例,即使您说您为 viewDidLoad()
访问权限没有区别,但这确实意味着无论您何时使用该变量,它都将保存一个真实值而不是 nil。
它们都是UILabel
.
我不确定为什么您不能使用 CGRect
构造函数将变量设置为新的 UILabel
,这应该是可能的。也许你曾经说过 let label = UILabel()
,这意味着它是一个不能保存新值的固定变量 - 所以你所能做的就是改变已经存在的变量的框架。
像你正在做的事情的最佳方法是将变量声明为可选:
var label : UILabel?
这使它成为一个真正的可选,并确保您不会意外编写错误地访问变量的代码,如果它从未被设置,或者在您分配 "real" 之前为您的第一个标签设置一个值viewDidLoad
方法中的 UILabel。访问有点不同,但并不难 - 要设置文本,您只需使用“?”如果实例已设置,可选择调用 属性 的语法:
label?.text = "fred"
你是对的。 UILabel()
调用 UILabel
无参数构造函数并将该对象引用分配给 label
变量。所以这是一个声明和一个初始化。
在构造函数的情况下,label
不是可选的,被推断为直接的 UILabel
类型,但在声明的情况下 label
是一个Optional
类型。这 !只是意味着它是一个可选的强制展开,所以当你将它用作一个值时,你不必输入 !;但是,如果您将其声明为强制展开并在其值为 nil
时使用它,您的程序将崩溃。
另请注意,您不能申报:
var label: UILabel
作为 class 成员 除非您在所有构造函数中初始化它,在(可能是隐式的)调用 super.init() 之前,因为它会抱怨没有初始值,因此它可能被引用时没有已知值——Swift 编译器会阻止这种情况。