如何理解Swift中Optional的 ! 和 ?
来源:互联网 发布:淘宝店铺模板在线制作 编辑:程序博客网 时间:2024/05/18 09:06
很多人在刚上手swift时对于Optional中 ‘!’ 和 ‘?’ 的使用十分不理解,接下来我会谈一谈自己对于这两个符号的使用方式的理解。
先来说说Optional的概念,以方便之后的理解。来看一下下面的代码:
var a : String = nil // 编译错误,String类型不能为nilvar b : String = “Hello!”
Swift 中的普通类型不再能设为nil。那如何表示这个值不存在呢?所以引进了Optional的概念:代表 nil 或某个具体的值。例如:
var c : String? = nil var d : String? = “Hello!”
String? 就是一个Optional,它既能够被具体类型赋值, 也可以赋值为nil。通过 String 和 Optional的比较,发现Optional 就相当于把具体类型和 nil 打包捆绑在了一起,转变成了一种新的类型。
Optional 有两种声明方法:
var apple: String? var bread: String!
很多人认为,声明为 String! 的变量表明该变量的值不为 nil。但是,实际上,String! 和 String? 都是有默认值的,且默认值都为nil。我们为它们赋一个初值再打印类型来看看:
var apple: String? = “apple” var bread: String! = “bread”
(lldb) p apple(String?) $R0 = “apple”(lldb) p bread(String?) $R1 = “bread”
发现,尽管apple 和 bread 虽然一个是 String? 一个是 String! 但是打印出来都是 String? 类型的。所以更恰当的理解应该是:String! 只是理解意义上的不为nil,其本质还是一个 Optional,从声明来说它和 String? 完全等价,所以也能够赋值为 nil 。
为了之后叙述方便,我们把定义类似 String? 的称为 Optional(?), 定义类似 String! 的称为 Optional(!)。
Optional 的本质是囊括 nil 和具体类型的一种枚举。获取它具体值的操作过程称之为拆包,用 “!” 表示。先来做个实验:
var string : Stringvar optionalString: String? var nonOptionalString: String!string = nonOptionalString // ① 崩溃string = optionalString // ② 编译错啦string = optionalString! // ③ 崩溃
具体看一下报错原因:
① String! 赋值给 String ,报错为:拆包时Optional的值为nil;
② String? 赋值给 String,编译器报错为 Optional未拆包;
③ 拆包后的 String? 赋值给 String,这时,报错为:拆包时Optional的值为nil;
String! 和 拆包后的 String? 进行传值时报的错相同,由此我们可以得出一个结论:编译器默认 Optional(!) 是确定有值的,所以不需要再对 nil 的情况进行处理。Optional(!) 的变量只是给予了自动拆包的权限,在实际使用它的过程中不需要再次使用 ‘!’ 进行拆包。在swift官方文档中称为:Implicitly Unwrapped Optional (隐式拆包),也可以理解成“拆过包了”。
但是,只有在变量确认有值的情况下才能进行拆包。就像如上代码,optionalString 为nil,进行拆包就会引发崩溃。swift官方建议,Optional 使用 if + ! 结合的方式或者 if let 进行安全地拆包。简单的看下代码:
if optionalString != nil { append(string: optionalString!)} else { // do something}
if let actualString = optionalString { append(string: actualString)} else { // do something}
再次提醒一下,Optional(!) 和 Optional(?) 都可以使用这两种方式进行安全地拆包,只是编译器不会对没有处理 nil 情况的 Optional(!) 报错。
下图展示了 Optional 和 String 可接收类型的比较:
拆完包之后的 Optional 其实就是 String 类型。编译器强制使用者在变量为 nil 的时候要进行处理,否则就会报错会崩溃。String! 是为了规避变量一定不为 nil 的情况下却要反复判断是否为 nil 的冗余代码而产生的。例如,我们在使用 IBOutlet 时,一定会定义成 Optiona(!)。String! 在声明时和 String? 完全等价,在使用时和 String 完全等价。
总结一下:
- Optional的本质是一个包含了 nil 和普通类型的枚举,这是为了确保使用者在变量为 nil 的情况下会完成相应的处理;
- 无论是 Optional(!) 还是 Optional(?) 都是一种Optional,在未设初始值时,默认为nil。Optional(!) 只是给予了自动拆包的权限,省略了判断其值是否为nil的过程,但是不能够保证它的值不为nil;
- Optional(!) 在声明时和 Optional(?) 等价,在使用时和具体类型等价;
- 一定要确保 Optional 不为 nil 的情况下才可直接拆包,不然会引发崩溃。
- 如何理解Swift中Optional的 ! 和 ?
- 如何理解Swift中Optional的!和?
- 理解Swift中Optional类型-有和无的哲学
- 对swift中的Optional和闭包的理解
- 理解Swift中的Optional
- swift 中,protocol的optional方法
- Swift Optional Type(问号?和感叹号!)的理解和使用
- Swift的Optional类型
- 深入浅出Swift的Optional ?!
- Swift的optional
- Swift的Optional、Array
- Swift的Optional
- swift中出现Optional("xxx")
- swift中(Optional)类型
- swift入门 之Optional ! 和 ?
- swift 学习笔记|Optional、?和!
- unexpectedly found nil while unwrapping an Optional value的解释 && Swift中Optional
- swift3.0 unexpectedly found nil while unwrapping an Optional value的解释 && Swift中Optional
- w10安装oracle, 正在检查操作系统要求... 实际结果: 6.2
- SpringCloud-----SpringCloud调用服务时出现重复调用
- Java四类八种数据类型
- SAN,DAS,NAS的介绍和区别
- Centos6启动故障之MBR破坏与修复
- 如何理解Swift中Optional的 ! 和 ?
- java完整的利用itext7制作pdf、二维码图片插入pdf,并解析pdf中的二维码信息
- Java集合类总结
- react-router 4.0 下服务器如何配合BrowserRouter/hashBrowserRouter
- 调用日志的注意事项
- HTML5新增的3种选择器
- 在GET请求方法中,实现向现有URL的末尾添加查询字符串参数
- 360安全卫士的HOOK
- QT学习_第一课:计算圆的面积