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]数组

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

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

转载于:https://www.cnblogs.com/motoyang/p/4783979.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值