何时使用?,!,None或Lazy?

时间:2015-06-28 07:24:40

标签: ios iphone swift variables optional

我刚开始学习Swift,最近发现了

  1. “正常”变量(缺少更好的名称):

    例如:var test1: String

  2. “可选”变量

    例如:var test2: String?

  3. “隐式解包的选项”

    例如:var test3: String!

  4. 懒惰变量

    例如:lazy var test4: String

  5. 我的理解是:

    1. 使用“可选”变量(?)当变量可能会或可能不会在将来从初始化开始的点初始化

    2. 当保证变量初始化时,使用“隐式展开的选项”(!)

    3. 可通过“强制解包”

      将期权转换为隐式解包期权

      例如:let possibleString: String? = "Hello" println(possibleString!)

    4. 在初始化之前不需要设置某些内容时使用“Lazy variables”(似乎这些可以与(?)或(!)一起使用)

    5. 因此,我的问题是:

      1. 我什么时候使用选项1 - 没有变量?没有!

      2. 我何时使用“懒惰”

      3. 我认为“懒惰”通常用于singletons - 为什么?

      4. 我对Java和C ++术语有最丰富的经验,如果这有助于我的回答背景。

        编辑:这是我找到的所有内容(主要问题是“正常” vs “隐式解包的选项”

        1. “正常”变量必须初始化:(a)在同一行,(b)在使用前的相同范围内(使用意味着对象的某些操作),(c)由init的结尾 iff 变量是一个字段。 注意:init的范围是类范围内的所有内容,而不是类中函数的范围。
        2. 打印隐式解包的可选将打印“nil”,但使用变量的函数将抛出运行时异常。同时,使用(完全包括打印) Normal 变量将不允许程序完全编译
        3. 使用目的! over“”(Nothing)是(a)更宽松,因为程序将编译(并且在变量实际初始化的情况下正确运行)和(b)允许您不要在一开始就初始化所有内容。 注意:如果正常变量,则任何字段未声明是编译时错误。

3 个答案:

答案 0 :(得分:2)

不完全是这样。

必须在首次使用之前初始化所有变量,并且必须在相应的初始化程序中为所有类/结构存储的属性赋值。可选项并不是指在某些时候被允许未被初始化,而是被允许不包含任何值,由nil表示,这仍然完全是这种变量的初始化陈述。因此,如果在初始化时无法知道某些内容,那么您可能会使用某种可选项(例如视图的委托)。

隐式解包的选项是变量可能为空的情况的一种简写,但我们绝对相信当我们真正使用它时它会保存一个实际值(典型的例子是视图控制器中的属性)持有对视图的参考)。

强制解包不会将可选转换为隐式展开的可选,而是它会为您提供一个值(如果它在那里是nil),如果不是,则会抛出异常。

如果您希望将初始化推迟到稍后阶段(当属性实际上是第一次使用时),则使用延迟属性。通常的情况是,如果您需要访问昂贵的资源来执行此操作(从磁盘加载大量文件,通过网络下载等),尤其是如果可能存在根本不会使用此类属性的情况(为什么要加载)它来自磁盘,如果我们不会使用它吗?)。

答案 1 :(得分:1)

让我们看一下Apple的例子

class Person {
    var residence: Residence?
}

class Residence {
    var numberOfRooms = 1
}

Residence实例有一个名为numberOfRooms的Int属性,默认值为1. Person实例具有Residence类型的可选驻留属性。

如果您创建一个新的Person实例,则其residence属性默认初始化为nil,因为它是可选的。

1。如果属性需要默认值为零 - 请使用可选。使用变量没有?而且! - 喜欢' numberOfRooms' -

您可以在初始化程序中设置存储属性的初始值,如上所示。或者,将默认属性值指定为属性声明的一部分。通过在定义属性时为其指定初始值来指定默认属性值。

请注意

  

如果属性始终采用相同的初始值,请提供默认值   值而不是在初始值设定项中设置值。结束   结果是相同的,但默认值绑定属性的   初始化更接近其声明。它缩短了,   更清晰的初始化程序,使您能够推断属性的类型   从它的默认值。默认值也使您更容易   利用默认初始化器和初始化器继承。

2。 !用于访问变量包含在变量中的值,当它不是nil时,否则抛出异常。所以,你可以使用!为了给你的用户做标记 - '当你打开它时,这个值不会为零

3。 使用延迟变量,如果您想稍后启动它,而不是在创建整个对象时,而是在您向getter请求数据时。当属性存储数组时,这很有用,例如:

lazy var players: [String] = {
        var temporaryPlayers = [String]()
        temporaryPlayers.append("John Doe")
        return temporaryPlayers
        }()

我什么时候应该使用延迟初始化?

何时使用延迟初始化的一个示例是,在初始化对象之后才知道属性的初始值。

答案 2 :(得分:0)

简短说明:

非可选变量总是一个值,永远不能为零。 必须在init方法或声明行中初始化变量。

var a : String
var b = "bar"

init {
    a = "foo"
}

隐式展开的可选变量必须在init方法中初始化 或在声明行中,但保证在使用时始终具有值

var a : String!

func viewDidLoad() {
    a = "Hello"
    a += " world!"
}

可选变量可能有一个值,在声明

时为零
var a : String?  // = nil

懒惰变量在第一次使用时被初始化

class foo {
  lazy var bar : String = {
    return "Hello"
    }()
}