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

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

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

  • 相关阅读:
    @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
    提交本地项目到github
    php魔术方法和魔术常量
    zTree学习
    js跨域解决方案(转载)
    启动apache和tomcat端口被占用解决办法
    配置nginx+php
    php,nginx重启
    php自动加载
    php命名空间
  • 原文地址:https://www.cnblogs.com/motoyang/p/4783979.html
Copyright © 2020-2023  润新知