异常处理、类型转换 ( Any and AnyObject )

1、错误处理 (异常处理)

swift 提供第一类错误支持 ,包括在运行时抛出 ,捕获 , 传送和控制可回收错误。在swift中 ,错误用复合 ErrorType 协议的值表示 。 Swift枚举把一系列相关的错误组合在一起。同时可以把一些相关的值和错误关联在一起 。 因此

编译器会为实现ErrorType协议的Swift枚举类型自动实现相应的合成

这里看个很简单的小例子。

  1. enum WrongName:ErrorType{
  2. case NoName
  3. }
  • 1
  • 2
  • 3

错误处理 1、抛出 
在方法后面加上throws 关键字

  1. func doSomeThing(name:String) throws ->String {
  2. if(name.isEmpty){
  3. throw WrongName.NoName
  4. }
  5. print("no error")
  6. return name
  7. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

当字符位空 , 我们就 throw 这个异常 。 
在调用一个抛出函数的时候 需要在调用前面加上try

  1. try doSomeThing("eat") //这里并没有出现异常 会输出 no error
  • 1
  1. try doSomeThing("") //会产生运行时错误 error caught in main()
  • 1

这里抛出了错误但是没有处理 。

2、捕捉和处理错误 do-catch 语句来捕捉和处理错误

语法 :

  1. do {
  2. }catch parttern{
  3. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

如果一个错误被爆出 , 这个错误会被传递到外部域 ,直到被catch捕捉处理 ,pattern 是用来匹配错误和相应的执行语句。

swift处理异常和别的语言不同的是swift不会展开调用堆栈 。 那样会带来很大的性能损耗 。 在swift中 throw 语句的性能几乎和return一样

  1. do{
  2. try doSomeThing("")
  3. }catch WrongName.NoName{
  4. print("NoName error!")
  5. } //输出NoName error!
  • 1
  • 2
  • 3
  • 4
  • 5

通过try!来调用抛出函数或者方法 来禁止错误传输 。并把调用包装在运行时断言,这样就不会抛出错误啦。如果帧抛出错误, 会触发运行时错误

  1. func willThrowIfTru(value:Bool) throws{
  2. if value {
  3. throw NotTrue.BeTrue
  4. }
  5. }
  6. do{
  7. try willThrowIfTru(true)
  8. }catch {
  9. print("不能为true呀")
  10. }
  11. //这里会输出 不能为true呀 --没有疑问
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  1. try! willThrowIfTru(false) //这块禁止了错误传输 意思断言肯定不会有异常 , 如果有 就会报错
  • 1

收尾操作

使用defer 执行的语句 不管有没有出错都回执行到 。相当于其他的finally

defer 语句和的执行顺序和它定义顺序相反 也就是说 , 第一个difer语句中的代买在第二个后执行 。

  1. func willThrowIfTru1(value:Bool) throws{
  2. if value {
  3. throw NotTrue.BeTrue
  4. }
  5. }
  6. do{
  7. try willThrowIfTru1(true)
  8. }catch {
  9. print("不能为true呀")
  10. }
  11. defer{
  12. print("我后执行")
  13. }
  14. defer{
  15. print("我先执行")
  16. }
  17. print("我第一个执行")
  18. 结果:
  19. 不能为true
  20. 我第一个执行
  21. 我先执行
  22. 我后执行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

2、类型转换

Swift 中使用is 和 as操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型

  • 用类型检查操作符(is)来检查一个实例 是否属于特定子类型
  1. class Person{
  2. var name:String
  3. init(name:String){
  4. self.name=name
  5. }
  6. }
  7. var p = Person(name: "wangwu")
  8. if p is Person
  9. {
  10. print("yes")
  11. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这里输出yes , 转换这种明显的没有什么意思 。来看看下面的、


  1. class Student: Person {
  2. }
  3. class Teacher: Person {
  4. }
  5. let list = [ Student(name: "张三") , Student(name: "李四") , Teacher(name: "王五") ]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这里会推断出是一个[Person] 数组

  1. var stuCount = 0
  2. var teaCount = 0
  3. for item in list {
  4. if item is Student {
  5. stuCount++
  6. }
  7. if item is Teacher{
  8. teaCount++
  9. }
  10. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  1. print("stu :\(stuCount) , tea: \(teaCount)")
  2. //stu :2 , tea: 1
  • 1
  • 2

这里利用is推断出具体类型

  • 向下转型 
    某类型的一个常量或变量可能在幕后实际上属于一个子类 这时候 你可以尝试向下转型 用as! 或者 as? 向下转型可能会失败 。as? 返回你试图转型的可选值 。 as! 强制转型 ,非常确定的时候再用 否则会运行时错误 。

所以上面的例子还能这么写

  1. stuCount = 0
  2. teaCount = 0
  3. //这里使用了可选绑定 以前的章节有讲过
  4. for item in list {
  5. if let s = item as? Student {
  6. stuCount++
  7. }
  8. if let t = item as? Teacher{
  9. teaCount++
  10. }
  11. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  1. print("stu :\(stuCount) , tea: \(teaCount)")
  2. //stu :2 , tea: 1
  • 1
  • 2

结果是一模一样的

  • Any 和 AnyObject 的类型 
    Swift为不确定类型提供了两种特殊类型别名: 
    AnyObject可以代表任何class类型的实例。 
    Any可以表示任何类型,包括方法类型(function types)。(2.0新特性)
  1. let student:[AnyObject] = [Student(name: "ww"),Student(name: "aa"),Student(name: "dd")]
  • 1
  1. //这里定义了一个[AnyObject] 类型的数组 ,但是确定是放得student 所以你可以强制转型
  2. let stu = student[0] as! Student
  3. print(stu.name) //aa
  4. let stus = student as! [Student]
  5. //你可以直接强制转换成一个Student数组
  6. print(stus.count) //3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

下面看下 Any类型

  1. var things = [Any]()
  2. things.append("str")
  3. things.append(0.9)
  4. things.append(stu)
  5. things.append(stus)
  6. for item in things {
  7. switch item {
  8. case let val as Double:
  9. print("\(val) 是个数字类型")
  10. case let val as String:
  11. print("\(val) 是个字符串")
  12. case let val as Student:
  13. print("\(val) 是Student对象")
  14. case let val as [Student]:
  15. print("\(val) 是个[Student]数组")
  16. default:
  17. print("啥都不是")
  18. }
  19. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

结果 :

  1. str 是个字符串
  2. 0.9 是个数字类型
  3. Student Student对象
  4. [Student, Student, Student] 是个[Student]数组

再不确定类型的时候才使用这两个 ,确定的时候最好使用确定类型

版权声明:本文为博主原创文章,未经博主允许不得转载。

swift详解之十-------------异常处理、类型转换 ( Any and AnyObject )的更多相关文章

  1. 异常处理器详解 Java多线程异常处理机制 多线程中篇(四)

    在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ...

  2. Solon 框架详解(十)- Solon 的常用配置

    Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...

  3. Swift详解之NSPredicate

    言:谓词在集合过滤以及CoreData中有着广泛的应用.本文以Playground上的Swift代码为例,讲解如何使用NSPredicate. 准备工作 先在Playground上建立一个数组,为后文 ...

  4. 【Java入门提高篇】Day34 Java容器类详解(十五)WeakHashMap详解

    源码详解系列均基于JDK8进行解析 说明 在Java容器详解系列文章的最后,介绍一个相对特殊的成员:WeakHashMap,从名字可以看出它是一个 Map.它的使用上跟HashMap并没有什么区别,所 ...

  5. 【Java入门提高篇】Day30 Java容器类详解(十二)TreeMap详解

    今天来看看Map家族的另一名大将——TreeMap.前面已经介绍过Map家族的两名大将,分别是HashMap,LinkedHashMap.HashMap可以高效查找和存储元素,LinkedHashMa ...

  6. Spring Boot 集成 FreeMarker 详解案例(十五)

    一.Springboot 那些事 SpringBoot 很方便的集成 FreeMarker ,DAO 数据库操作层依旧用的是 Mybatis,本文将会一步一步到来如何集成 FreeMarker 以及配 ...

  7. Git应用详解第十讲:Git子库:submodule与subtree.md

    前言 前情提要:Git应用详解第九讲:Git cherry-pick与Git rebase 一个中大型项目往往会依赖几个模块,git提供了子库的概念.可以将这些子模块存放在不同的仓库中,通过submo ...

  8. Redis详解(十)------ 从零开始搭建集群

    在上一篇博客我们介绍了------Redis哨兵(Sentinel)模式,哨兵模式主要是解决高可用问题,在master节点宕机时,slave节点能够自动切换成为master节点 本篇博客我们来介绍Re ...

  9. Java源码详解系列(十)--全面分析mybatis的使用、源码和代码生成器(总计5篇博客)

    简介 Mybatis 是一个持久层框架,它对 JDBC 进行了高级封装,使我们的代码中不会出现任何的 JDBC 代码,另外,它还通过 xml 或注解的方式将 sql 从 DAO/Repository ...

随机推荐

  1. python __builtins__ list类 (42)

    42.'list', 转换为列表类型 class list(object) | list() -> new empty list | list(iterable) -> new list ...

  2. bzoj 2648: SJY摆棋子【KD-tree】

    其实理论上cdq更优 核心是依次取x值.y值的mid作为当前节点,向两边递归建立二叉树,树上维护size:子树大小:mx[0/1]:子树内最大x/y:mn[0/1]:子树内最小x/y:d[0/1]:这 ...

  3. P5162 WD与积木(多项式求逆+生成函数)

    传送门 题解 比赛的时候光顾着算某一个\(n\)的答案是多少忘了考虑不同的\(n\)之间的联系了--而且我也很想知道为什么推着推着会变成一个二项式反演-- 设\(f_n\)为\(n\)块积木时的总的层 ...

  4. UVA - 10817 Headmaster's Headache

    题目大意:有一些老师,每一位都有自己的工资以及教授的课程.共s<=8个课程.其中的一些老师必须选择,问你保证每节课至少有一个老师的最少总工资. 题解: 首先很容易想到状态压缩,搞一个3进制的数, ...

  5. Java Web中实现设置多个域名跨域访问

    添加以下设置可允许所有域名跨域访问: response.setHeader("Access-Control-Allow-Origin","*"); 但在实际应用 ...

  6. vs2015未能正确加载“ProviderPackage”包

    出现以下错误的解决方案 ---------------------------Microsoft Visual Studio---------------------------未能正确加载“Prov ...

  7. asp,php,jsp 不缓存网页的办法

    ASP实例源码浏览次数:4 一般地,我们要查看Internet 网上的一个网页,那么 当您第一次访问这个网页的时候, 系统首先要将这个网页下载到您的本地计算机 的一个临时文件夹中进行缓存, 当在一定的 ...

  8. python之url编码

    import urllib.parsempp='besttest 自动化测试'print(urllib.parse.quote_plus(mpp)) #url编码print(urllib.parse. ...

  9. UWP 后台保存图片

    在做UWP的时候,有一个需求,就是点击下载按钮,需要将当前页面中的Image控件中显示的图片保存下来. 既然聊到了下载图片,索性把添加图片也讲一下. 一:给Image控件添加图片 xaml代码: &l ...

  10. [NOIP2018校模拟赛]T1 阶乘

    题目: 描述 有n个正整数a[i],设它们乘积为p,你可以给p乘上一个正整数q,使p*q刚好为正整数m的阶乘,求m的最小值. 输入 共两行. 第一行一个正整数n. 第二行n个正整数a[i]. 输出 共 ...