optional
optional是swift特有特征(oc没有),定义对象为optional表示对象可能有值,可能无值
- optional:可能有值,可能无值
- non-optional:任何时候都有值(即使值无意义),不存在无值
nil
- 在oc中,nil表示指针,指向不存在对象,只能赋值给指针对象
- 在swift中,nil表示optional无值,只能赋值给optional
注:未初始化optional默认为nil
forced unwrap optional
func forced_unwrap()
{
var food1: Int? = 5
var food2: Int? = nil
print("food1 nil: \(food1 == nil), food1 not nil: \(food1 != nil)")
print("food2 nil: \(food2 == nil), food2 not nil: \(food2 != nil)")
print("food1:\(food1)")
print("food1!: \(food1!)")
print("food2:\(food2)")
print("food2!: \(food2!)")
}
output:
food1 nil: false, food1 not nil: true
food2 nil: true, food2 not nil: false
food1:Optional(5)
food1!: 5
food2:nil
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
总结:
- 可通过!=或==与nil比较确认optional有值或无值
- 可通过惊叹号(!)获取optional值,这个行为称为forced unwrap optional,即强制性打开
- optional有值,forced unwrap optional获取optional值,程序正常运行,optional无值,forced unwrap optional则runtime error,程序crash
optional binding
func optional_binding()
{
let food1: Int? = 5
let food2: Int? = nil
print("food1: \(food1)")
print("food2: \(food2)")
let rice = food1
let meat = food2
print("rice: \(rice)")
print("meat: \(meat)")
if let rice = food1
{
print("rice: \(rice)")
}
else
{
print("rice value absent")
}
if let meat = food2
{
print("meat: \(meat)")
}
else
{
print("meat value absent")
}
let food3: Int? = 8
let food4: Int? = 18
let food5: Int? = 28
if let rice = food3, let meat = food4 where rice != meat, let fruit = food5
{
print("rice: \(rice) meat: \(meat), fruit: \(fruit)")
}
else
{
print("some value absent")
}
}
output:
food1: Optional(5)
food2: nil
rice: Optional(5)
meat: nil
rice: 5
meat value absent
rice: 8 meat: 18, fruit: 28
总结:
- let(var) rice = food1成为语句和成为条件表达式一部分意义完全不同
- let(var) rice = food1成为语句等同于let(var) rice: Int? = food1,只是简单定义和初始化,rice还是optional
- let(var) rice = food1成为条件表达式一部分等同于若optional food1有值,let(var) rice:Int = food1!,且表达式值为true,若optional无值,表达式值为false,此即为optional binding,用代码表示Bool ret = (rice != nil ? rice = food1!, true : false)
- 多个optional binding可并存于条件表达式中,optional binding之间用逗号(,)分隔,optional binding和non-optional binding表达式之间用where分隔,non-optional binding和optional binding之间用逗号(,)分隔,此处逗号(,)等同于&&,where亦等同于&&,因此let rice = food3, let meat = food4 where rice != meat, let fruit = food5等同于let rice = food3 && let meat = food4 && rice != meat && let fruit = food5
implicitly unwrap optional
func implicit_unwrap()
{
let food1:Int? = 5;
let food2:Int! = 8;
print("food1:\(food1)")
print("food1!:\(food1!)")
print("food2:\(food2)")
print("food2!:\(food2!)")
}
output:
food1:Optional(5)
food1!:5
food2:8
food2!:8
总结:
- 如果能确认optional一直有值,可定义为implicitly unwrap optional,这样可省略每次获取optional值时unwrap optional
- implicitly unwrap optional定义使用惊叹号(!),而非问好(?),这是implicitly unwrap optional和normal unwrap optional的外观区别
- implicitly unwrap optional本质还是normal unwrap optional,因此仍可把implicitly unwrap optional当normal unwrap optional使用,包括forced unwrap optional和optional binding
- implicitly unwrap optional只是假设一直有值,但不确保一定有值,implicitly unwrap optional仍可能无值,若implicitly unwrap optional无值,获取implicitly unwrap optional值时仍会runtime error