Swift中的可选类型 (Optionals)与Objective-C中的nullability注解

来源:互联网 发布:php网上商城系统源码 编辑:程序博客网 时间:2024/06/05 10:29

Swift:可选类型 (Optionals)


1.Swift:可选类型 (Optionals)概述

 在Swift中,当声明一个变量时,默认情况下是 不可选类型(non—optional)—即必须指定一个不为nil的值,如果非要把一个不可选类型的变量设为nil,那么编译器就会警告


在类中声明的变量也是这样,默认情况下是不可选类型


总结:在swift中,有俩种情况下,编译器会针对变量做出警告:(1)将变量设置为nil时

      (2)变量没有初始值时



使用oc声明一个字符串,如果将字符串设置为nil,不会有任何问题



如果要在swift中声明一盒没有初始化的变量,可以使用swift提供了可选类型来表示没有值的情况。只需要在声明的类型后面加上问号?即可;也可以给可选类型的变量赋值,如果不赋值那么它的值自动设为nil


总结:在swift中,如果不想让没有初始化值的变量报警告,那么就将该变量设置为可选变量(加上问号?),可以给变量赋值,也可以不赋值(自动设为nil)


2.可选类型在swift中使用的原因

swift是一门类型安全的语言,它的可选类型会进行编译检查,防止一些常见的运行时错误

式例:(在oc中运行以下代码)


调用:


以上代码在编译时不会有任何问题,如果输入的是其他字符串,就会返回nil,最终导致运行时崩溃


式例:(在swift中运行以下代码)


在上面的代码中,stockCode使用了?,被定义成了可选类型,意味着他可以有一个sting值,也可以为nil。代码无法通过变异

正如在例子中看到的,swift的可选类型加强了nil检测,为开发者提供了编译时的检查,合理的使用可选类型可以有效的i提高代码质量


3.强制解析

如果想让上边代码通过编译,需要使用if判断stockCode不为nil时,才执行代码,并且在stockCode后面加上一个感叹号!进行解析

加上感叹号进行解析,这样xcode就知道了:嗯我可以使用这个值了,在swift里称之为强制解析,通过感叹号强制获取可选类型的真实值


如果把if判断去掉,但仍然添加感叹号


这样不会得到编译错误,因为我们用了强制解析,编译器已经假定这个可选类型肯定有值,但是运行时会崩溃


4.可选绑定

除了强制解析,可选绑定(optional binding)是一个更值得推荐的解析方案。可以使用可选绑定来检测一个可选类型的值有没有值,如果有值则解析出来并存储到一个临时变量


if let(或者 if var)是可选绑定的俩个关键词。如果stockCode有值,把他的值存到tempStackCode里,然后继续执行接下来的代码块。如果他没有值,则跳过后面的代码块。

因为tempStackCode是一个新的常量,所以不需要添加感叹号


可以把方法调用放在 if 里,这样代码看起来更简洁:这里stockcode不再是可选类型,如果返回了nil则跳过后面的代码块



5.可选链

1.如果遇到很多需要使用if let的变量,那么if嵌套过于复杂了,这时可以使用可选链来使代码更加清晰整洁


Objective-C:nullability注解

1.概述

通过Bridging-Header文件,swift可以与oc无缝调用,但是swift与oc有一个很大的不同点:swift支持optional类型,如 NSView 和 NSView?,在oc里对此只有一种表示,即NSView*,既可以用来表示该view为nil,也能表示为非nil,此时swfit编译器是无法确定这个NSView是不是optional类型的,这种情况下swift编译器会把它当作NSView!处理,隐式拆包。

Xcode6.3发布了一个oc的新特性:nullability注解,利用该特性我们也能对自己的代码进行类似的处理


2.核心注解 __nullabel 和 __nonnull

__nullabel可以表示一个NULL或者nil值;

__nonnull则不能表示一个NULL或者nil值

例如:


在方法定义或声明里,只要类型是一个简单的对象或者Block指针,就能以不带下划线的方式直接加在左括号后面:


对于@property,也能以同样的方式写在他的属性列表里



3.审查区域

如果要把每个头文件的类型都加上核心注解,那么会很麻烦,此时就用到了审查区域,可以把头文件的某个区域标记为审查区域,在这个区域内,所有简单的指针类型都会被当作nonnull


xcode6.3(iOS 8.3)引入了 NS_ASSUME_NONNULL)BEGIN /END 宏

上面的代码itemWithName方法的name参数没有使用Nullability特征,但会被当作nonnull处理


4.审查区域使用规则

> typedef 定义的类型不会继承nullability特性,它们会根据上下文选择nullabel或non_nullabel,所以,就算在审查区域内,typedef定义的类型也不会被当作nonull

> id*这样更复杂的指针类型必须被显示的注解,比如,要指定一个nonull的指针为一个nullabel的对象引用,那么需要使用__nullabel id* __nonnull

> NSError**这些特殊的、通过方法参数返回错误对象的类型,将总是被当作是一个nullabel的指针指向一个nullabel的指针 ,__nullabel NSError ** __nullabel


1 0
原创粉丝点击