swift基础之错误处理

使用到的关键字

throw 抛出一个错误异常 **

throws** 定义一个throwing函数 放在 返回类型 -> 前

**try** 调用throwing函数

**do { try throwing函数 } catch  错误枚举case  {  处理 }** 错误处理*

*defer  {}**  清除数据,内存,资源, defer语句 在代码块中最后执行可以清理一些资源

**guard** 简化代码使用,guard的执行取决于一个条件语句的bool值,类似于if ,与if 不同的是,guard 必定有一个else分支(条件不为真),可以把值 传递到后面使用,可以在可选类型转换的时候,把可选类型的值传递到后面使用错误处理介绍:错误处理是在程序里对错误情况的响应和恢复swift 支持在运行时抛出、捕获、传送可操作可恢复的错误

一般使用先使用枚举 定义自己的错误类型,实现ErrorType协议



/*  介绍 */

/*

 错误处理是在程序里对错误情况的响应和恢复

 swift 支持在运行时抛出、捕获、传送和操作可恢复的错误

 

建立自己的错误枚举

需要先定义一个错误枚举,实现ErrorType 协议

 

 抛出一个错误 使用 throw

 表示一个throwing函数 使用 throws  用在返回箭头-> 之前

 调用throwing 函数 使用try 关键字

 处理错误使用do catch,把定义的枚举错误全部抛出

do {
    try throwsFun()
 }catch error.case1{
    code
 }catch error.case2{
    code
 }

 

 将错误转化为可选值

 try

 try!

 try?

 

 defer {} 语句经行清理资源等,因为在函数内部 defer 语句 是最后一个执行的

 

 guard 语句 简化代码 类似 if ,不同于if 的是,guard 必定有一个else语句 

 它可以在转换可选类型的时候 把转换可选值 传递到下面使用

 

*/





/* 表示和抛出错误 */

/*
 表示错误
 错误遵循ErroyType这个空协议类型的的值来表示,比如使用枚举来表示一组错误,让枚举来实现ErroyType
 
 抛出错误 throw

 */

//IP地址
"192.168.1.1"
enum IPError: ErrorType {
    case TooFewComponents
    case TooManyComponents
    case OctetWasBad(Int)
    case OctetNotNum(String)
}
// 抛出错误   throw IPError.TooFewComponents

/* 处理错误 */
/*
 四种处理
 传递错误
 throw  do {  }catch{}
 将错误当成可选类型来处理
 断言错误它不会发送
 */

//传递错误
/*

 1、throwing传递错误 使用throws 关键字 来表示一个可抛出错误的函数,在函数声明列表后加一个 throws  关键字 就被称为 throwing函数

 2、调用 throwing函数 需要使用 try 关键字

 

 3、处理错误

 使用 do catch

 

*/
func convertIP1(ipArray:String) throws {
    
    let components = ipArray.componentsSeparatedByString(".")
    if components.count == 4 {
        print("success count")
    }else if components.count < 4{
        
        throw IPError.TooFewComponents
    }
    else{
        throw IPError.TooManyComponents
    }
}

func convertIP2(ipArray:String) throws -> Int{
    
    let components = ipArray.componentsSeparatedByString(".")
    if components.count == 4 {
        print("success count")
    }else if components.count < 4{
        
        throw IPError.TooFewComponents
    }
    else{
        throw IPError.TooManyComponents
    }
    var  total = 0
    for (index,value) in components.enumerate() {
        
        if let num = Int(value) {
            
            if num >= 0 && num <= 255 {
                total += num
                
            }else{
                throw IPError.OctetWasBad(index)
            }
            
        }else{
            throw IPError.OctetNotNum(value)
        }
    }
    return total
}
//调用throwing 函数
//try convertIP1("192.168")
//try convertIP2("192.169.1.a")

//处理错误
do {
    try convertIP2("192.168.a.a")
    
} catch IPError.TooFewComponents{
    print("TooFewComponents")
}catch  IPError.TooManyComponents{
    print("TooManyComponents")
}catch IPError.OctetWasBad(let num){
    print("超过了255 或 低于 0 \(num)")
}catch IPError.OctetNotNum(let str){
    print("不是数字 \(str)")
}


/* 将错误转化为可选值
 try
 try?  throwing函数 转化成可选值,成功 为值,不成功为nil
 try!  throwing 函数 确定不会抛出错误 ,就使用try! 返回值不是可选值
 */

let optionalTotal =  try? convertIP2("192.168.1.12")
optionalTotal.dynamicType

// 指定清理方法   defer
/*
 使用defer 语句 在代码执行到 离开当前代码段之前执行一套语句
 这个语句能够让我们做一些应该在代码作用完成之后执行一些必要的清理工作
 defer 语句会在执行完代码块 完成之后,准备离开代码块之前执行
 
 defer  可以对资源经行释放,等
 */

func someClass()  {
    defer {
        print("代码执行完 进行清理 \(name)")
    }
    var name : String = "我"
    name.appendContentsOf("邪恶")
    
    print("代码执行完成 \(name)")
}
var some = someClass()

/* guard  简化代码
 
 guard 的执行 取决于一个条件语句的bool值,类似于if ,不同于id 的是,guard 必定有一个else语句(条件不为真),在可选转换的时候,它可以把可选转换的值传递到下边  
 
 */
//使用guard 替换 if 简化代码 ,下面等同于convertIP2
func convertIP3(ipArray:String) throws -> Int{
    
    let components = ipArray.componentsSeparatedByString(".")
    
    guard components.count == 4 else {
        if components.count < 4{
            
            throw IPError.TooFewComponents
        }
        else{
            throw IPError.TooManyComponents
        }
    }
    
    var  total = 0
    for value in components {
    
        guard let num = Int(value) where num >= 0 && num <= 255 else {
            throw IPError.OctetNotNum(value)
        }
        total += num
    }
    return total
}

/*

 错误处理

 先枚举一个错误,实现ErrorType 协议

 抛出错误

  throw error.电话号码不为数字

 定义一个throwing 函数

 处理错误

*/
enum error:ErrorType {
    case 电话号码不为数字(String)
    case 电话号码长度不为11
    case 电话号码不以1开头
}
func phoneNumber(number:String) throws  {
    
    
    defer {
        print("clear array")
        ary = []
    }
    
    var ary : [Character]  = []
    for charace in number.characters{
//        if Int(String(charace)) != nil {
//             ary.append(charace)
//        }else{
//        
//            throw error.电话号码不为数字(String(charace))
//        }
        //等同于上面
        guard Int(String(charace)) != nil else{
             throw error.电话号码不为数字(String(charace))
        }
        ary.append(charace)
        
    }
    if ary.count == 11 {
        
        if ary[0] == "1" {
            
        }else{
            throw error.电话号码不以1开头
        }
        
    }else{
        throw error.电话号码长度不为11
    }
 
//    guard ary.count == 11 else {
//        throw error.电话号码长度不为11
//    }
//    guard ary[0] == "1" else{
//        throw error.电话号码不以1开头
//    }
}

do {
    try phoneNumber("wqe")
}catch error.电话号码不为数字(let value){
    print("电话号码不为数字 \(value)")
}catch error.电话号码长度不为11 {
    print("电话号码长度不为11")
}catch error.电话号码不以1开头 {
    print("电话号码不以1开头")
}

输出结果


success count

不是数字 a

success count

代码执行完成 我邪恶

代码执行完 进行清理 我邪恶

clear array

电话号码不为数字 w