swift详解之十-------------异常处理、类型转换 ( Any and AnyObject )

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

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

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

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

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

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

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

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

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

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

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

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

语法 :

do {

}catch parttern{

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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

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

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

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

func willThrowIfTru(value:Bool) throws{
    if value {
        throw NotTrue.BeTrue
    }
}

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

收尾操作

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

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

    func willThrowIfTru1(value:Bool) throws{

        if value {
            throw NotTrue.BeTrue
        }
    }
  do{
            try willThrowIfTru1(true)
        }catch {
            print("不能为true呀")
        }

        defer{
            print("我后执行")
        }

        defer{
            print("我先执行")
        }
        print("我第一个执行")
        结果:
        不能为true呀
        我第一个执行
        我先执行
        我后执行
  • 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)来检查一个实例 是否属于特定子类型
class Person{
    var name:String
    init(name:String){

        self.name=name
    }
}

var  p = Person(name: "wangwu")
if p is Person
{
    print("yes")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

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


class Student: Person {

}
class Teacher: Person {

}

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

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

var stuCount = 0
var teaCount = 0

for item in list {

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

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

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

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

stuCount = 0
teaCount = 0

//这里使用了可选绑定 以前的章节有讲过
for item in list {

    if let s = item as? Student {
        stuCount++
    }
    if let t = item  as? Teacher{
        teaCount++
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
print("stu :\(stuCount) , tea: \(teaCount)")
//stu :2 , tea: 1
  • 1
  • 2

结果是一模一样的

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

下面看下 Any类型

var things = [Any]()

things.append("str")
things.append(0.9)
things.append(stu)
things.append(stus)

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

结果 :

str  是个字符串
0.9  是个数字类型
Student  是Student对象
[Student, Student, Student]  是个[Student]数组

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

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

时间: 2024-08-27 04:31:14

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

swift详解之十四 -----------NSThread 异步下载图片

NSThread 异步下载图片 在IOS中处理多线程有三个方案 , NSThread .NSOperation .GCD .当然GCD应该是最方便的 ,我们一个一个学 .先理解底层的,最后再使用最方便的 . NSThread: 优点:NSThread 比其他两个轻量级 缺点:需要自己管理线程的生命周期,线程同步.线程同步对数据的加锁会有一定的系统开销 我们先研究下用NSThread 异步加载网络图片 : NSThread有两种创建方式 ,一种是通过实例方法.一种是通过类方法. let threa

swift详解之十二-----------------泛型

泛型 注:本文详细讲解泛型,对写一些公共方法,共用的东西的时候很有帮助.想成为一个优秀的程序员吗?这个必须掌握 泛型代码可以让你写出根据自我需求定义.适用于任何类型的,灵活可重用的函数和类型. 下面直接看一个简单的示例 , 泛型其实就是在写的时候不指定是哪种类型 , 只有再用得时候才指定类型 ,这些类型可以给一些限定.例如 Array Dictionary 等 写一个简单的交换数据的方法,不限定类型 func swapTwoValue<T>(inout a:T,inout _ b:T){ le

swift详解之十九--------------UITableView的基本操作(下拉刷新,新增删除,分组,检索等)

UITableView的基本操作(下拉刷新,新增删除,分组,检索等) 注:本小结总结UITableview的一些基本用法 UITbleView继承自UIScrollView,只能用来显示一列数据(目前就只认识到这里),纵向滑动. 一般有两种方式来实现,直接用UITableViewController , 占满整个屏幕 .不用手动实现UITableViewDataSource 和UITableViewDelegate .另一种方式在UIViewController 中.我们看看这种方式 let t

swift详解之十八------------ScrollView

ScrollView 注:本小节详细介绍scrollView的用法 UIScrollView是一个能够滚动的视图控件,可以用来展示大量的内容,并且可以通过滚动查看所有的内容 UIScrollView的用法,将需要展示的内容添加到UIScrollView中 设置UIScrollView的contentView属性,告诉UIScrollView所有内容的尺寸 let scroll = UIScrollView(); scroll.backgroundColor = UIColor.grayColor

swift详解之十六-----------GCD基础部分

GCD基础部分 注:本节主要详细讲解线程同步的一些基本概念和GCD基础部分 GCD (Grand Central Dispatch) 首先我们来了解处理线程中的一些基本概念 : 串行:同时只能有一个任务被执行 并发:同时可以有多个任务执行 同步:同步任务会阻塞当前线程,知道任务完成 异步:预定的任务会完成但不会等它完成,因此,一个异步函数不会阻塞当前线程去执行下一个函数. 临界区:就是一段代码不能被并发执行,也就是,两个线程不能同时执行这段代码.(不同代码去操作共享资源可能会变质) 死锁:多个线

swift详解之十五------------NSThread线程同步锁

NSThread线程同步锁 上小节用NSThread实现读取网络图片 , 这节用NSThread 模拟一个卖票的例子 .用NSLock 或者NSCondition 锁定资源 var total = 100 //总票数 var w1 = 0 //窗口1卖出票数 var w2 = 0 //窗口2卖出票数 var isSell = true //是否出售 var lock:NSLock? var condition:NSCondition? 这里首先定义一些变量 然后再点击卖票的时候,开启连个线程模仿

C++ stringstream详解-安全高效的类型转换

在头文件<sstream>中包含. string 到int 的转换 string result="10000"; int n=0; stream<<result; stream>>n;//n等于10000 如果你打算在多次转换中使用同一个stringstream对象,记住再每次转换前要使用clear()方法: 在多次转换中重复使用同一个stringstream(而不是每次都创建一个新的对象)对象最大的好处在于效率.stringstream对象的构造和

Linux下套接字详解(十)---epoll模式下的IO多路复用服务器

epoll模型简介 epoll可是当前在Linux下开发大规模并发网络程序的热门人选,epoll 在Linux2.6内核中正式引入,和select相似,其实都I/O多路复用技术而已,并没有什么神秘的. 其实在Linux下设计并发网络程序,向来不缺少方法,比如典型的Apache模型(Process Per Connection,简称PPC),TPC(Thread PerConnection)模型,以及select模型和poll模型,那为何还要再引入Epoll这个东东呢?那还是有得说说的- 常用模型

swift详解之二十二-----------UINavigationController的基本用法和页面传值几种方式

UINavigationController的基本用法和页面传值几种方式 本文介绍UINavigationController基本用法,因为涉及多页面顺便介绍页面传值 1.手写代码创建UINavigationController 手写方式创建很简单 , 首先创建一个项目 , 默认是从storyboard 加载的.这时候首先去掉默认加载方式 . 然后在AppDelegate.swift 的didFinishLaunchingWithOptions 中创建 代码如下: func applicatio