【问题标题】:What's the difference between var label: UILabel! and var label = UILabel( )?var label: UILabel 和有什么区别!和 var label = UILabel( )?
【发布时间】:2015-02-26 04:01:09
【问题描述】:

我注意到,当我用 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() 既声明又实例化了一个类对象,而var label: UILabel! 只是声明了一个类型的变量?我对这里实际发生的事情感到困惑。

提前致谢!

【问题讨论】:

  • 你可以写var label: UILabel! = UILabel(),不是吗?这是什么意思(尤其是必须稍后设置框架)?在没有明确类型的情况下查找Type Inference - 例如。带有“:” - 指定。
  • 所以var label: UILabel! 正在设置一个名为 label 的变量,其类型为 UILabel,var label = UILabel() 正在创建一个类实例并简单地推断 UILabel 类型(这就是为什么不需要 : UILabel!) ? var label = UILabel() 是 var label: UILabel! = UILabel(),只是因为类型推断而变得简写?
  • 是的。类型推断是 Swift 的核心。这并不比 var x = 3 将 x 推断为 Int 更令人惊讶。
  • 我想我的大脑已经快要意识到这一点了。感谢 BaseZen!对我来说是一个真正的 /headdesk 时刻。

标签: ios swift uilabel


【解决方案1】:
var label: UILabel!

声明您有一个可能为空的 UILabel 变量(可选),但您可以假装它不会访问它 - 通常这意味着它将是一个 IBOutlet 将由界面故事板在加载时设置,在您尝试使用标签之前。

var label = UILabel()

声明您有一个标签,该标签将始终持有标签,并且永远不能为零。在创建类实例时也会创建 UILabel 的实例,即使您说您为 viewDidLoad() 中的变量分配了不同的标签

访问没有区别,但这确实意味着无论您何时使用该变量,它都会保存一个真实值而不是 nil。

它们都是UILabel类型的变量。

我不确定您为什么不能使用CGRect 构造函数将变量设置为新的UILabel,这应该是可能的。也许你曾经说过let label = UILabel(),这意味着它是一个不能保存新值的固定变量——所以你所能做的就是改变已经存在的变量的框架。

像您正在做的事情的最佳方法是将变量声明为 Optional:

 var label : UILabel?

这使它成为一个真正的可选,并确保您不会意外编写代码访问该变量,如果它从未被设置,或者在您分配“真正的”UILabel 之前为您的第一个标签设置一个值@ 987654329@ 方法。访问有点不同,但并不难 - 设置文本只需使用“?”如果已设置实例,则可选择调用属性的语法:

label?.text = "fred"

【讨论】:

  • “我不知道你为什么不能使用 CGRect 构造函数将变量设置为新的 UILabel,这应该是可能的。”我也是,我认为这是我困惑的真正根源。
  • 刚刚添加了一个关于可能发生的事情的想法。
  • 这很有意义。我想有一次我在声明中玩弄 let 和 vars 只是为了看看会发生什么。可能是这些测试中我的代码的残余。谢谢!
  • 最后一个后续问题:哪些声明会被视为“最佳实践”?我想在未来提高我的标准。再次感谢!
  • Swift 的最佳实践(在我看来)会使用 var 标签:UILabel?。接下来是 var label : UILabel! (这是 Interface Builder 默认创建的),但前提是您真的非常确定在调用 viewDidLoad() 之前没有任何内容会访问标签(在访问视图之前创建视图控制器实例和访问属性非常容易)。最后是 var label = UILabel(),主要是因为它创建了两个标签实例(尽管您可以切换到 let label = UILabel() 并只使用一个实例,但我认为对其他人来说似乎“奇怪”)。
【解决方案2】:

你是对的。 UILabel() 调用 UILabel 无参数构造函数并将该对象引用分配给 label 变量。所以这是一个声明和初始化。

在构造函数的情况下,label 不是可选的,并且被推断为直接的UILabel 类型,但在您的声明的情况下label 是 @987654327 @ 类型。这 !只是意味着它是带有强制展开的可选,因此当您将其用作值时,您不必键入!;但是,如果您将其声明为强制解包并在其为 nil-valued 时使用它,您的程序将崩溃。

另请注意,您不能声明:

var label: UILabel

作为一个类成员除非你在所有构造函数中初始化它,否则在(可能是隐式的)调用 super.init()之前因为它会抱怨没有初始值,所以它可能会以不知道的值被引用——这是 Swift 编译器阻止的。

【讨论】:

  • "但是,如果您将其声明为强制解包并在它为 nil 值时使用它,您的程序将崩溃。"哦,是的,我已经非常熟悉那个了 :) 感谢您的快速回答!
猜你喜欢
  • 2019-09-21
  • 2018-12-07
  • 1970-01-01
  • 1970-01-01
  • 2013-06-28
  • 2011-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多