在Swift中声明实例变量:optional vs forced unwrapping vs initial value

时间:2016-06-26 13:04:40

标签: ios swift initialization instance-variables

这是关于swift中使用实例变量声明swift类的最佳实践的基本问题,所有值都将从Firebase回调中接收。这些选择中最好的方法是什么,或者让我知道是否有另一种更好的方法:

解决方案1:

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
    } 
}

2 个答案:

答案 0 :(得分:4)

使用隐式展开的选项几乎不是一个好主意。您应该这样想:如果您确定始终拥有name的{​​{1}},则应使用User字符串初始化对象:

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也具有误导性,因为你必须实现检查字符串是否为空或包含名称。

答案 1 :(得分:1)

使用

之类的东西
var name:String = ""

说你有一个变量名,它将被初始化为""对于所有对象

var name:String?

是说您知道变量名称将在此对象中,并且此name属性可以包含值nil。以这种方式承认它的存在意味着你必须在使用之前初始化它。这样可以让您获得更多控制权。在大多数情况下,只有像

这样的东西
String name;

在其他语言中意味着如果您在没有明确初始化的情况下使用名称,那么您将获得一个空字符串。这不是这里的情况。使用,您说这个属性 name 绝对存在于所有对象中,但它可能包含也可能不包含数据,但是因为您使用明确创建了它?然后您知道某个事实,包含数据。

var name:String!

这有点像var name:String =""在文件的顶部。使用,您说当您创建对象时,您将能够使用name属性,因为它已经初始化了。这就是为什么IBOutlets有而不是的原因。原因是因为它已经为您设置了。它在您使用之前已初始化

之间的混淆来自于没有正确使用它们。如果您完全掌控了项目,并且知道什么时候进入和不使用,并且您可以控制何时创建,那么最好使用。在一个完全控制的独立环境中,您想要使用,因为它会像您习惯的编程一样

但是,如果您开始添加有条件的视图控制器之间的交互,并且您知道在某些时候您将需要名称属性,但是您只是不知道该怎么办? t确切知道什么时候?那你可以说:

"嘿我可以使用并检查它是否包含""是否"

这可能有用而且它很好但是如果你在整个应用程序中没有实际使用该属性的情况下占用空间。当大多数视图都是有条件的时候,你基本上都是为所有情况编程。

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

是什么
var name:String

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

那么

会是什么呢?
print(name)

运行时对编译器意味着什么?好吧,在你真正运行它之前,你不会知道。这是一个问题,但

print(name!)

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