Martin

思想空间

我是Martin,iOS / Android 开发者。


欢迎来到我的思想空间

swift 可选值

swift 可选值总结

先看几个例子:

            var optionalStr : String!
             //声明可选值,默认为nil
             optionalStr = nil
             if optionalStr == nil {
             //    通过条件判断
             }

当初看到这段代码时,非常奇怪,按照之前浅显的理解,被标记为!的应该必然有值啊,这段代码应该报错才对啊?后面仔细查看文档,才理解了这段代码

Optional的定义

Optional也是Objective-C没有的数据类型,是苹果引入到Swift语言中的全新类型,它的特点就和它的名字一样:可以有值,也可以没有值,当它没有值时,就是nil。此外,Swift的nil也和Objective-C有些不一样,在Objective-C中,只有对象才能为nil,而在Swift里,当基础类型(整形、浮点、布尔等)没有值时,也是nil,而不是一个初始值,没有初始值的值,是不能使用的,这就产生了Optional类型。

简单来说:

             var nonoptionalStrStr: String                

这是非可选类型

             var optionalStrStr: String? 
             var optionalStrStr: String!

这都是可选类型

非可选类型的特点

             var nonoptionalStrStr: String                  
             NSLog(nonoperationStr)
             //error: variable 'nonoperationStr' used before being initialized
             //表示非可选类型必须初始化才能使用
             
             nonoperationStr = nil
             //error: nil cannot be assigned to type 'String'
             //说明 nil 也是一种数据类型,不能够赋值给string类型的对象,
             //从这个角度说,使用非可选类型更不容易出错

可选类型

显式拆包

Optional类型的值不能被直接使用,当需要用时要显式拆包,以表明我知道这个Optional是一定有值的:

                 var str: String? = "Hello World!"
				 str! //Hello World!

对比拆包前后,对str的输出

               var str: String? = "Hello World!"
               str     //{Some "Hello World!"}
               str!    //Hello World!

之所以要拆包使用,是因为Optional类型其实是一个枚举:

               enum Optional<T> : Reflectable, NilLiteralConvertible {
               case None
               case Some(T)
               init()
               init(_ some: T)

               /// Haskell's fmap, which was mis-named
               func map<U>(f: (T) -> U) -> U?
               func getMirror() -> MirrorType
               static func convertFromNilLiteral() -> T?
              }

当Optional没有值时,返回的nil其实就是Optional.None,即没有值。除了None以外,还有一个Some,当有值时就是被Some包装的真正的值,所以我们拆包的动作其实就是将Some里面的值取出来。

隐式拆包

除了显式拆包,Optional还提供了隐式拆包,通过在声明时的数据类型后面加一个感叹号(!)来实现:

            var str: String! = "Hello World!"
            str //Hello World!     

可以看到没有使用(?)进行显式的折包也得到了Some中的值,这个语法相当于告诉编译器:在我们使用Optional值前,这个Optional值就会被初始化,并且总是会有值,所以当我们使用时,编译器就帮我做了一次拆包。如果你确信你的变量能保证被正确初始化,那就可以这么做,否则还是不要尝试为好。

所以,使用!真的是一件非常危险的事,它并不表示这个值使用一定是安全的,它只是表明开发人员认为这个值有值,编译器并不会检查,不小心很容易出错。

最近的文章

swift 类型转换笔记

swift 类型转换笔记AnyObject为了便于理解,你可以认为AnyObject是一种“type”(实际上并不是type),就像Double,Array等,AnyObject主要用于兼容现有的Objective-C API和iOS代码,swift不能用AnyObject构建自己的数据结构,swift是强类型语言,并有类型推断的特性。什么是AnyObject?在哪会看到AnyObject?AnyObject的意思是指向一个对象的指针,也就是一个对象的实例,但你不知道它是什么class,所...…

总结知识管理继续阅读
更早的文章

iOS面试题整理

iOS面试题整理autorelease 嵌套, 系统是怎么处理的?在`NSAutoReleasePool`中会有一个array保存所有需要被`autorelease`的对象, 由于我们要确保在保存对象时array不会对该对象进行强引用(retainCount plus 1), 我们需要用CFMutableArrayRef.由于每一个线程都有自己的autoReleasePool, 所以我们需要保存该线程中所创建的所有autoreleasepools,每创建一个autoreleasepool,...…

总结知识管理继续阅读