swift编程,不外乎是定义属性或者函数(方法),访问属性或者调用函数,类型转换,?和!在这几个过程中,都有一展身手的时候,而且,每次要考虑使用的时候,它们俩都会一起出现在我们的大脑中,用还是不用,如果用,要用谁?


1、定义属性

“?”表示可选类型(Optionals),“!”表示隐式可选类型(全名:implicitly unwrapped optionals),其实还是可选类型。

可选类型,就是将已存在的某种类型(结构体、枚举、类)定义为可选类型,表示该“新”类型的值可以为空nil。书写格式就是在原来的类型后面跟一个“?”比如:

var nickName : String?

定义了一个可选类型String?的变量nickName,如果我们不在构造函数(init这类函数)中给nickName赋初值,那么,系统会默认给它一个nil为初值,其实,我们定义的可选类型的时候,系统马上就把可选类型变量或常量初始化为nil了,在调用init方法之前。

在访问可选类型属性时,如果我们确定该属性在这个时候一定有值,可以在属性名称后面加“!”,告诉系统,“我肯定这个可选属性有值,强制取出来用”,但是,如果这个可选类型属性当时的值为nil,那么会crash。(如果访问属性或者调用函数,必须用“!”或者“?”,下文再说),照样访问,这样,如果是nil,也不会因为这个导致crash。所以,一般在程序的关键点使用可选类型之前,都会做安全检查,判断实际值是否为nil。判断方法有两种:

swift:

if nickName  != nil {  print("\(nickName)") }

if let tempName = nickName {  print("\(tempName)") }

//第二种写法叫可选绑定,意思是,如果可选类型nickName不为nil,就取出其中的值,赋给tempName,并且类型推断tempName为NSString,因为确定等号后面的那个量不为nil才执行赋值,所以,tempName 不是可选类型,赋值成功,此时相当于if true {。。。}

“ !” ,隐式可选类型,就是可选类型,书写位置同 “ ?”,区别是,用“!”声明的可选类型,访问属性的时候都可以不用写“!”来取出属性的真实值,这就告诉系统,我知道这个属性在其存活过程中一直会有值。其实,在控制器中访问自己的可选类型属性是需要用“!”来取值的,这个动作官方叫强制解包(forced unwrapping)。上面说取值,为了方便理解。

var nickName :String!

注意:如果隐式可选类型属性在生命周期中可能会为nil,那还是不要将其定义为“!”类型的了。会crash的。


2、定义函数?

“?”和“!”是可以用来定义函数的。类、结构体、枚举都是需要构造器的,那么,有时候根据某种业务要求,我们会判定,本次实例构造过程失败,于是,就有了可失败构造器。官方文档里面举例如下:

class Product {

let name: String!

init?(name: String) {

self.name = name

if name.isEmpty { return nil }

}

}

所以,看到init?和init!的时候不要慌,就是要实例化的类型可能是空,可能构造(创建)失败,失败的时候会返回nil,虽然swift不想OC中那样需要在init方法中返回self。上例中,如果构造成功,比如:

let newProduct = Product("巧克力")

根据Product类定义,构造实例成功,newProduct的类型推断为Product?。(除非你硬要在接收实例的变量或常量后面加个可选类型,不要作,真的。。。)

作为基友,怎么能没有“!”的事!其实作用一样,只是,如果构造成功,返回实例的类型推断为Product!(隐式可选)

有一点需要强调的是,如果当前实例化的类为某个类的子子子类,比如我们自定义了一个UIButton的子类BaseButton,又定义了PYButton :BaseButton,实例化PYButton的时候,如果失败了,那么在实例化过程中继承者链条无论进行到哪一步了,就马上停止。


3、访问属性和调用函数

在我们访问属性或者调用函数的时候,因为swift允许各种连语法连在一起用,所以,有时候会出现一大串点语法连续调用,属性访问和函数调用相互交叉,在这个过程中,如果遇到可选类型怎么办?要写一堆“!”解包?答案是否定的。

swift提供了一个机制,叫“可空链式调用”,在一连串的点语法调用和访问中,只需要在调用者后面加一个“?”,表示,如果这一串点语法执行过程中,任何一步失败,整个点语法链条就会停止,并且作为一个整体返回nil,不会报错,不会crash。那么,问题来了,用“!”不行么?可以!但是,如果在点语法链条中,那一步返回值为nil,就会导致crash。既然我们没法永远保证某块代码返回值不为nil,或者属性为nil,或者失败,那么用“ ?”是极好的。

上代码:

class Person {

var telString :String?

}

let xiaoMing  = Person()

print("\(xiaoMing.telString!.intValue)") //crash,因为telString为nil,强制解包就crash

print("\(xiaoMing.telString?.intValue)") //输出:nil

4、类型转换

大家都知道OC中有多态,某些情况下,我们会将子类实例赋值给父类指针,用到的时候,再强转回子类。swift中,这种情况,使用as? 和 as! 来做,如果要判断某个实例的类型 用 is。 A as? B的意思是,如果实例A是B类型或者是B类型的子类,就将A的类型转化成B类型,并返回转换后的实例(是可选类型B?),如果不是,表达式返回nil,程序继续运行。如果用as! ,说明我们肯定A是类型B或者B的子类实例,那么,强制转换,如果不是,那么会crash。比如,

class Teacher : Person {

var teachingID : String

init(teachingID : String) {

self.teachingID = teachingID

super.init()

}

}

class Student : Person {

var studentID : String

init(studentID : String) {

self.studentID = studentID

super.init()

}

}

let teacher = Teacher("12345")

let student = Student("987")

let classContact = [teacher,student]

//注意:此时classContact的类型是:[Person]

for person in classContact {

if let teacher = person as? Teacher { //code}

else if let student = person as? Student { // code}

}

简单提一下,is,它就相当于 OC中的 isKindOfClass:方法。

另外,还有两个问号连在一起用的,其实也很简单,先看代码:

let  name = “panyu”

let  nickName = name ?? "hehe" //如果name为nil(当然本例不会为nil),那么表达式返回值为"??"之后的值,如果name有值,那么表达式返回name本身的值

一句话,?? 表达式就是三目运算符的简单版。

Swift的基础之关于“!”和“?”的使用介绍的更多相关文章

  1. [Swift]基础

    [Swift]基础 一, 常用变量 var str = "Hello, playground" //变量 let str1="Hello xmj112288" ...

  2. Swift之基础知识

    Swift之基础知识 出于对Swift3.0的学习,写下这篇基本语法的笔记.希望能帮助记忆 -0- 这边提供Swift3.0中文教材,资源链接: https://pan.baidu.com/s/1c2 ...

  3. Swift语法基础入门三(函数, 闭包)

    Swift语法基础入门三(函数, 闭包) 函数: 函数是用来完成特定任务的独立的代码块.你给一个函数起一个合适的名字,用来标识函数做什么,并且当函数需要执行的时候,这个名字会被用于“调用”函数 格式: ...

  4. Swift语法基础入门四(构造函数, 懒加载)

    Swift语法基础入门四(构造函数, 懒加载) 存储属性 具备存储功能, 和OC中普通属性一样 // Swfit要求我们在创建对象时必须给所有的属性初始化 // 如果没办法保证在构造方法中初始化属性, ...

  5. Swift语法基础入门二(数组, 字典, 字符串)

    Swift语法基础入门二(数组, 字典, 字符串) 数组(有序数据的集) *格式 : [] / Int / Array() let 不可变数组 var 可变数组 注意: 不需要改变集合的时候创建不可变 ...

  6. swift编程语言基础教程 中文版

    swift编程语言基础教程 中文版 http://download.csdn.net/detail/u014036026/7845491

  7. 【转】Java基础笔记 – 枚举类型的使用介绍和静态导入--不错

    原文网址:http://www.itzhai.com/java-based-notes-introduction-and-use-of-an-enumeration-type-static-impor ...

  8. Java基础-JAVA中常见的数据结构介绍

    Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...

  9. Django基础核心技术之Model模型的介绍与设计

    Django基础核心技术之Model模型的介绍与设计原创: Yunbo Shi Python Web与Django开发 2018-05-03Django网络应用开发的5项基础核心技术包括模型(Mode ...

  10. HTML&CSS基础-前端免费开发工具Hbuilder介绍

    HTML&CSS基础-前端免费开发工具Hbuilder介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 工欲善其事必先利其器,想要干好活得有一个好的工具. 一.文本编辑工 ...

随机推荐

  1. Linux 下的一个全新的性能测量和调式诊断工具 Systemtap, 第 3 部分: Systemtap

    Systemtap的原理,Systemtap与DTrace比较,以及安装要求和安装步骤本系列文章详细地介绍了一个Linux下的全新的调式.诊断和性能测量工具Systemtap和它所依赖的基础kprob ...

  2. hbase大规模数据写入的优化历程

    业务背景:由于需要将ngix日志过滤出来的1亿+条用户行为记录存入Hbase数据库,以此根据一定的条件来提供近实时查询,比如根据用户id及一定的时间段等条件来过滤符合要求的若干行为记录,满足这一场景的 ...

  3. Android输入控件详解

    输入控件 输入控件是您的应用用户界面中的交互式组件.Android 提供了多种可在 UI 中使用的控件,如按钮.文本字段.定位栏.复选框.缩放按钮.切换按钮等. 向 UI 中添加输入控件与向 XML ...

  4. Python 文本转语音

    文本转语音,一般会用在无障碍开发.下面介绍如何使用Python实现将文本文件转换成语音输出. 准备 使用Speech API 原理 示例代码 小总结 pyttsx方式 原理 示例代码 小总结 pytt ...

  5. 4-sum问题

    给定一个整数数组,判断能否从中找出4个数a.b.c.d,使得他们的和为0,如果能,请找出所有满足和为0个4个数对. #define SIZE 10 void judgeAndPut(int* arr, ...

  6. 有两个序列A和B,A=(a1,a2,...,ak),B=(b1,b2,...,bk),A和B都按升序排列。对于1<=i,j<=k,求k个最小的(ai+bj)。要求算法尽量高效。

    有两个序列A和B,A=(a1,a2,...,ak),B=(b1,b2,...,bk),A和B都按升序排列.对于1<=i,j<=k,求k个最小的(ai+bj).要求算法尽量高效. int * ...

  7. Java实现内部类

    内部类是java中非常方便的一种机制,内部类所在的类称为宿主类,即内部类只能被它的宿主类使用,用这个特性,可以很好的控制类的可见性. 接下来看一个例子: package for_apro; impor ...

  8. 【IOS 开发】基本 UI 控件详解 (UISegmentedControl | UIImageView | UIProgressView | UISlider | UIAlertView )

    转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/50163725 一. 分段控件 (UISegmentedControl) 控件展 ...

  9. 浅谈Android布局

    在前面的博客中,小编介绍了Android的极光推送以及如何实现登录的一个小demo,对于xml布局页面,摆控件这块的内容,小编还不是很熟练,今天小编主要简单总结一下在Android中的布局,学习过An ...

  10. GDAL书籍中删除数据勘误(C#语言)

    GDAL书籍中关于C#版本删除数据的时候,不能完全删除数据,由于我对C#不了解导致代码有点问题,非常感谢@Bingoyin指出并给出修改方案.此外对于栅格图像的删除.重命名,矢量数据的删除和重命名都有 ...