optional一些理解和总结:
Optional作为一种类型,既可以存储一个值,也可以为空(也就是swift里的nil);
其实为一个枚举类型,包含nil或者一个值,如下;
enum Optional<T>: _Reflectable, NilLiteralConvertible {
case None
case Some(T)
//...
}
它只有两种状态,包含一个值或者为空;
optional有效解决了值为空的清空;
我们可以通过判断一个对象是否为空了做出相应解决,通过if let a = b(optional)的方式实现一个解包过程,并在条件中使用a,而不再解包;
针对anyobject,由于直到运行时才知道AnyObject的对象类型,所以有可能在不经意间写出不安全代码,
如:let timeSinceNow = myObject.timeIntervalSinceNow;
当一个anyobject类型的对象去调用某个方法,而该对象不存在此方法(optional对象调用方法会隐式展开),如下;
let timeSinceNow = myObject.timeIntervalSinceNow?(); ----此时当方法不存在时,timeSinceNow被推测为对应类型,并被赋予一个nil值;
接着可以使用if let方式判断来使用该对象;这个就避免了anyobject运行时才确定类型而报错的问题;
对于隐式解包:访问时,编译器会自动帮我们完成在变量后插入!
的行为
当我在项目中明确确定该属性一定会被初始化;且在使用范围内不会为空时,在声明属性时就可以使用!表示隐式解包;
这类属性主要这对UI控件,通常情况,控件都不会为空,这样避免了繁杂的解包过程以及判断过程;
隐式解包的来源摘自百度:
王巍在他的Swift Tip解释了一下:
这一切都是历史的锅。因为Object-C中Cocoa的所有类型变量都是可以指向nil的,有一部分Cocoa的API中在参数或者返回时即使被声明为具体的类型,但是还是可能在某些特定的情况下是nil, 而同时也有另一部分API永远不会接受或者返回nil。在Objective-C时,这两种情况并没有加以区别,因为在OC中向nil发送消息是允许的,结果就是什么都不会发生,而在Cocoa API从OC转为Swift的module声明的自动化工具里,是无法判定是否存在nil的可能的,因此也无法决定哪些类型应该是实际的类型,而哪些类型应该声明为Optional。
在这种自动化转换中,最简单粗暴的应对方式是全部转为 Optional,然后让使用者通过 Optional Binding 来判断并使用。虽然这是最安全的方式,但对使用者来说是一件非常麻烦的事情,我猜不会有人喜欢每次用个 API 就在 Optional 和普通类型之间转来转去。这时候,隐式解包的 Optional 就作为一个妥协方案出现了。使用隐式解包 Optional 的最大好处是对于那些我们能确认的 API 来说,我们可直接进行属性访问和方法调用,会很方便。但是需要牢记在心的是,隐式解包不意味着 “这个变量不会是 nil,你可以放心使用” 这种暗示,只能说 Swift 通过这个特性给了我们一种简便但是危险的使用方式罢了。
当然隐式解包也会有问题,尝试访问一个为空的隐式解包Optional,就会遇到一个runtime error;
这种问题在自己项目中最常见的就是在异步线程(主要为网络请求)中主动去调用控件;当对象销毁而线程延迟执行时就会崩溃;在调用对象前主动判断对象为空否。
针对optional的属性和方法,可以通过链(Optional Chaining)来实现安全访问,如同anyobject使用一样;
let b: Int?
if let a = b?.sum(){a的使用};-----摆脱很多不必要的判断和取值,从而精简代码。
swift中可以使用??
来设置一个默认值;
同上:if let a = b?sum() ?? 1 -----如果b为空了,给a赋值1;
设置默认值的方法在项目中很方便;
当你封装一个方法,而针对不同的调用者是??可有效解决调用者身份判断问题。
列:
func addNum(a: Int, b: Int, c: Int = nil) -> Int{if c == nil {return a + b} else (return a + b - c)}
而你在调用该方法时,系统会提供自动两个func;--------次方法在代码高度封装以及一些特殊判断中非常有效;
关于oc方法调用:oc中对象应用可以为NULL,而swift中必须为非空;所以当在swift中使用oc对象时必须保证其位非空;
以次文纪念我死在开发道路上的脑细胞。