【问题标题】:Declare instance variable in Swift : optional vs forced unwrapping vs initial value [closed]在 Swift 中声明实例变量:可选 vs 强制展开 vs 初始​​值 [关闭]
【发布时间】:2016-10-28 13:41:44
【问题描述】:

这是一个关于在 swift 中使用实例变量声明 swift 类的最佳实践的基本问题,所有值都将从 Firebase 回调中接收。这些选择中最好的方法是什么,或者如果有其他更好的方法,请告诉我:

解决方案一:

class User: NSObject {
    var name:String = ""

    override init() {
        super.init()
    }
}

解决方案 2:

class User: NSObject {
    var name:String!

    override init() {
        super.init()
    }   
}

解决方案 3:

class User: NSObject {
    var name:String?

    override init() {
        super.init()
    }   
}

解决方案 4:

class User: NSObject {

    var name:String

    override init() {
        super.init()
        // Now I need to init name variable here
    } 
}

【问题讨论】:

  • 如果您不需要两阶段初始化或与 Obj-C 交互,请不要使用 !。如果您不需要 nil 值,请不要使用可选项。这基本上就是您需要知道的全部内容。

标签: ios swift initialization instance-variables


【解决方案1】:

使用隐式展开的可选项几乎从来都不是一个好主意。你应该这样想:如果你确定你将永远拥有Username,你应该使用name 字符串初始化对象,如下所示:

class User: NSObject {
    let name: String
    init(name: String) {
        self.name = name
        super.init()
    }
}

如果你不确定你是否会在回调中得到name,请使用可选的字符串属性:

class User: NSObject {
    var name: String?
}

这将使您能够使用if let 来检查name 是否有值。

如果您使用String!,您的应用程序几乎肯定会在某一时刻崩溃,因为您访问了nil

var name: String = "" 也具有误导性,因为您必须实施检查字符串是否为空或包含名称。

【讨论】:

  • 我喜欢第一个选择,但在这种情况下,我需要初始化所有变量,并且我将拥有所有很长的 init 方法,而在现实生活中,我将拥有一本字典或另一个对象如何摆脱警告Property 'self.name' not initialized at super.init call
  • 你的答案很好,但是你把两种类型的选项的名字弄错了——?显式的,! 是隐式。所以你帖子的第一行应该是'Using implicitly unwrapped optionals 。 . . - 见andybargh.com/optionals-in-swift/…
  • 谢谢,我的错字,已修复。
【解决方案2】:

使用类似的东西

var name:String = ""

是说你有一个变量名,所有对象都会被初始化为 ""

var name:String?

是说您知道变量名称将在此对象中,并且此名称属性可以包含值 nil。以这种方式确认它的存在意味着您必须在使用它之前对其进行初始化。这给了你更多的控制权。在大多数情况下,只是有类似的东西

String name;

在其他语言中意味着如果您使用 name 而不显式初始化它,那么您将得到一个空字符串。这不是这里的情况。使用 ? 你是说这个属性 name 肯定存在于所有对象,但它可能包含也可能不包含数据,但是既然你使用 ? 那么你就知道在某个时候它应该包含数据。

var name:String!

这有点像文件顶部的 var name:String = ""。使用 ! 你是说在你创建一个对象的那一刻你就可以使用 name 属性,因为它已经被初始化了。这就是为什么 IBOutlets 有 ! 而没有 ?。原因是它已经为您设置好了。使用前已初始化

?! 之间的混淆来自于没有正确使用它们。如果您对项目有完全的控制权,并且您知道什么时候使用和停止使用,并且您可以控制创建的时间,那么最好使用 !。在完全受控的自包含环境中,您会想要使用 !,因为它会像您习惯的编程一样

但是,如果您开始在有条件的视图控制器之间添加交互,并且您知道在某些时候您将需要一个 name 属性,但您不知道确切的时间?好吧,你可能会说:

“嘿,我可以使用 并检查它是否包含“””

这可以工作,而且很好,但是如果您浏览整个应用程序而不在该实例中实际使用该属性,则会占用空间。当大多数视图都是有条件的时,您基本上是针对所有情况进行编程的。

这就是你选择的原因?? 表示您需要此属性。你可能不知道确切的时间,但它肯定是有目的的。即使它不存在,您仍然可以使用此属性编写逻辑,因为它允许您在不检查数据的情况下检查存在。这就是使选项如此出色的原因,因为当您编译应用程序时,Xcode 将能够梳理它并查看可选标志。然后它将开始处理可选的。这很重要,因为什么

var name:String

告诉你名字?是否已初始化?会吗?

然后呢

print(name)

在编译器运行时意味着什么?好吧,直到您实际运行它,您才会知道。这是一个问题,但是

print(name!)

强制解开可选的var name:String?。这允许编译器防止运行时错误,因为有人创建了一个结果是可选的属性。

【讨论】:

    猜你喜欢
    • 2012-06-04
    • 1970-01-01
    • 1970-01-01
    • 2019-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-14
    • 1970-01-01
    相关资源
    最近更新 更多