enum VendingMachineError:ErrorType{
case InvaildSelection //選擇無效
case InsufficientFunds(coinsNeeded:Int) //金額不足
case OutOfStock //缺貨無效
}
enum GetJSONError: ErrorType {
case Forbidden, NotFound
}
struct Item {
var price:Int
var count:Int
}
class ViewController: UIViewController {
func getJSON(aaa:Int) throws -> String {
let a = aaa
if a == 403 {
throw GetJSONError.Forbidden
}
else if a == 404 {
throw GetJSONError.NotFound
}
return "return JSON String Success"
}
var inventory = [
"Candy Bar":Item(price: 12, count: 7),
"Chips":Item(price: 10, count: 4),
"Pretzels":Item(price: 7, count: 11)
]
var coinsDeposited=4
func dispenseSnack(snack:String){
print("Dispensing\(snack)")
}
func vend(itemNamed name:String) throws{
guard var item=inventory[name] else{
throw VendingMachineError.InvaildSelection
}
guard item.count > 0 else{
throw VendingMachineError.OutOfStock
}
guard item.price <= coinsDeposited else{
throw VendingMachineError.InsufficientFunds(coinsNeeded: item.price - coinsDeposited)
}
coinsDeposited -= item.price
--item.count
inventory[name]=item
dispenseSnack(name)
}
//錯誤處理
//錯誤處理是響應錯誤以及從錯誤中恢復的過程。
//可選類型用來表示值可能爲空,但是當執行失敗的時候,通常要去了解此次失敗是由何引起,代碼中就可以做出與之相應的反應
//swift中,錯誤用遵循ErrorType協議類型的值來表示。這個空協議表示一種可以用做錯誤處理的類型。
//用throws關鍵字來標識一個可拋出錯誤的函數,方法或是構造器。在函數聲明中的參數列表之後加上throws,如果這個函數還有返回值類型,throws關鍵詞需要寫在箭頭的前面
//一個throwing函數從其內部拋出錯誤,並傳遞到該函數被調用時所在的區域中
//只有throwing函數可以傳遞錯誤。任何在某個非throwing函數內部拋出的錯誤只能在此函數內處理
override func viewDidLoad() {
super.viewDidLoad()
do{
try vend(itemNamed: "Pretzels")
} catch VendingMachineError.InvaildSelection {
print("InvaildSelection")
} catch VendingMachineError.OutOfStock {
print("OutOfStock")
} catch VendingMachineError.InsufficientFunds(let myCoinsNeed){
print(myCoinsNeed)
}catch{
print("error catched!")
} //3
do{
let json = try getJSON(404)
print(json)
} catch GetJSONError.Forbidden {
print("403 Forbidden")
} catch GetJSONError.NotFound {
print("404 Not Found")
} catch {
print("error catched!")
}//404 Not Found
//將錯誤轉換成可選值
//可以使用try?通過將其轉換成一個可選值來處理錯誤。如果在評估try?表達式時一個錯誤被拋出,那麼這個表達式的值就是nil。
let json = try? getJSON(404) //如果不加問號則會報錯:Errors thrown from here are not handled
print(json)//nil
//let json = try? getJSON(404)等價於:
let json2 : String?
do{
json2 = try getJSON(404)
}catch{
json2 = nil
}
print(json2)//nil
//使錯誤傳遞失敗
//有時你知道某個throwing函數實際上運行時是不會拋出錯誤的。在這種條件下,可以在表達式前面寫try!來使錯誤傳遞失敗,並且調用包裝在一個運行時斷言中來斷定不會有錯誤輸出。如果實際上確實拋出了錯誤,就會得到一個運行時錯誤
//指定清理操作
//可以使用defer語句在代碼執行到要離開當前的代碼段之前去執行一套語句。該語句讓你能夠做一些應該被執行的必要清理工作。defer語句將代碼的執行延時到當前的作用域之前。
}
// func processFile(filename:String)throws{
// if exists(filename){
// let file = open(filename)
// defer{
// close(file)
// }
// while let line = try file.readline(){
// //處理文件
// }
// //作用域的最後調用close(file)
// }
// }
// override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
// //保存觸摸起始位置
// let point : CGPoint = ((touches as NSSet).anyObject()?.locationInView(self.view))!
// maskLayer.frame=CGRectMake(point.x-50,point.y-50, 100,100)
// }
//UITouch的屬性和方法:
//view :屬性,觸摸始於那個視圖
//window:屬性,觸摸始於那個窗口
//locationInView:方法,觸摸在指定視圖中的當前位置
//previousLocationView:方法,觸摸在指定視圖中的前一個位置
// override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
// //計算位移=當前位置-起始位置
// let point:CGPoint = ((touches as NSSet).anyObject()?.locationInView(self.view))!
// maskLayer.frame=CGRectMake(point.x-50,point.y-50, 100,100)
// }
//
}