-
try catch
的使用示例
enum Error:ErrorType{
case error1
case error2
}
func f1() throws{
throw(Error.error2)
}
do{
try f1()
print("no error")
}catch Error.error1{
print("has error1")
}catch Error.error2{
print("has error2")
}
- 空合運(yùn)算符(
Nil Coalescing Operator
)
var a:Int?
let b:Int = 10
let c = a ?? b
print("c = \(c)")
ps.以上代碼類似
c = a != nil ?a! :b
但看起來更加優(yōu)雅
- 區(qū)間運(yùn)算符
for i in 1...5{
print("\(i) ")
}
for i in 1..<5{
print("\(i) ")
}
swift
中并沒有左開右閉區(qū)間
- 字符串的
utf-8 utf-16 unicode
表示
let s = "hello world"
for u in s.utf8{
print("\(u) ")
}
for u in s.utf16{
print("\(u) ")
}
for u in s.unicodeScalars{
print("\(u) ")
}
- 可變參數(shù)
func arithmeticMean(numbers:Double...) -> Double{
var total:Double = 0
for number in numbers{
total += number
}
return total/Double(numbers.count)
}
print("average number = \(arithmeticMean(1,2,3))")
- 函數(shù)類型
func addTwoInts(a:Int, b:Int) -> Int{
return a + b
}
var mathFunction:(Int,Int) -> Int = addTwoInts
print("\(mathFunction(3,4))")
- 函數(shù)作為參數(shù)類型
func printMathResult(math:(Int, Int) -> Int, a:Int, b:Int){
print("\(math(a,b))")
}
func add(a:Int, b:Int) -> Int{
return a + b
}
printMathResult(add,a:3,b:4)
- 函數(shù)作為返回類型
func stepForward(input:Int) -> Int{
return input + 1
}
func stepBackward(input:Int) -> Int{
return input - 1
}
func chooseStepFunction(backwards:Bool) -> (Int) -> Int{
return backwards ?stepBackward :stepForward
}
//這里的x 是一個(gè)函數(shù)類型
let f1 = chooseStepFunction(true)
print("f1 = \(f1(3))")
- 嵌套函數(shù)
func chooseStepFunction(backwards:Bool) -> (Int) -> Int{
func stepForward(input:Int) -> Int{return input + 1}
func stepBackward(input:Int) -> Int{return input - 1}
return backwards ?stepBackward :stepForward
}
//這里的x 是一個(gè)函數(shù)類型
let f1 = chooseStepFunction(true)
print("f1 = \(f1(3))")
- 閉包
sort
為swift
標(biāo)準(zhǔn)庫提供的方法 可以根據(jù)提供的排序規(guī)則對(duì)一個(gè)數(shù)組進(jìn)行排序 生成一個(gè)長度一致的新數(shù)組
以下使用了閉包表達(dá)式和函數(shù)方式 實(shí)現(xiàn)了排序
func backwards(s1:String, s2:String) -> Bool{
return s1 > s2
}
let names = ["C", "D", "E","A", "B"]
let sequenceNames = names.sort()
// let reversedNames = names.sort(backwards)
let reversedNames = names.sort({(s1:String, s2:String) -> Bool in
return s1 > s2
})
print("sqquence Names:\(sequenceNames) \nreversed Names:\(reversedNames)")
因?yàn)?code>sort方法 明確定義了閉包的參數(shù) 返回值所以可以進(jìn)一步簡寫為
names.sort{s1,s2 in s1 > s2}
可以使用$0 $1 $2
順序表示閉包的參數(shù) 所以可以再簡寫為
names.sort({$0 > $1})
swift
中的String
類型 定義了“>”的字符串實(shí)現(xiàn) 因此還可以簡寫為
names.sort(>)
不過 最好使用完整的閉包表達(dá)式 使代碼更具有更好的可讀性
- 尾隨閉包
可以將一個(gè)閉包表達(dá)式作為函數(shù)的最后一個(gè)參數(shù)傳入來增強(qiáng)函數(shù)的可讀性
let digitNames = [
"Zero","One", "Two", "Three", "Four", "Five",
"Six", "Seven", "Eight", "Nine"
]
let numbers = [123,785,951]
let strings = numbers.map{
(number) -> String in
var outPut = ""
var n = number
while n > 0{
outPut = digitNames[n%10] + outPut
n = n / 10
}
return outPut
}
print("strings = \(strings)")
- 非逃逸閉包 自動(dòng)閉包
這個(gè)現(xiàn)在看懂了
@escaping
逃逸閉包指的是閉包在函數(shù)返回后才執(zhí)行
@noescaping
則相反 在函數(shù)返回之前就執(zhí)行了
@autoclosure
指的是自動(dòng)創(chuàng)建的閉包,不能接受參數(shù),并且屬于非逃逸閉包 下邊是一個(gè)自動(dòng)閉包的例子昧互,
func printIfTrue(@autoclosure predicate: ()-> Bool){
if predicate(){
print("the result is true")
}
}
printIfTrue(2 > 1)
//直接進(jìn)行調(diào)用了屹蚊,Swift 將會(huì)把 2 > 1 這個(gè)表達(dá)式自動(dòng)轉(zhuǎn)換為 () -> Bool。這樣我們就得到了一個(gè)寫法簡單睡榆,表意清楚的式子唱蒸。
- 遞歸枚舉求值
indirect enum ArithmeticExpression{
case Number(Int)
case Addition(ArithmeticExpression, ArithmeticExpression)
case Mutiplication(ArithmeticExpression, ArithmeticExpression)
}
func evaluate(expression: ArithmeticExpression) -> Int{
switch expression {
case .Number(let value):return value
case .Addition(let l, let r):return evaluate(l) + evaluate(r)
case .Mutiplication(let l, let r):return evaluate(l) * evaluate(r)
}
}
let five = ArithmeticExpression.Number(5)
let four = ArithmeticExpression.Number(4)
let sum = ArithmeticExpression.Addition(five, four)
let product = ArithmeticExpression.Mutiplication(sum, ArithmeticExpression.Number(2))
print("sum:\(evaluate(sum)) product:\(evaluate(product))")
- 下標(biāo)腳本
struct TimeTable {
let multiplier:Int
subscript(index:Int) -> Int {return multiplier * index}
}
let threeTimesTable = TimeTable(multiplier:3)
print("\(threeTimesTable[6])")
- 弱引用示例
//適用于弱引用的場景 weak
//公寓和人 room對(duì)jack的引用為弱引用 jack為nil之后 room并不會(huì)為nil 但jack不會(huì)對(duì)room產(chǎn)生強(qiáng)引用 room為nil 會(huì)釋放其所占內(nèi)存空間 并不會(huì)因?yàn)閖ack的引用而不釋放
class Person{
let name: String
var apartment:Apartment?
init(name: String){self.name = name}
deinit {print("Person is being deinitialized")}
}
class Apartment{
let unit: String
weak var tenant: Person?
init(unit:String){self.unit = unit}
deinit {print("Apartment is being deinitialized")}
}
var jack:Person?
var room:Apartment?
jack = Person(name:"jack")
room = Apartment(unit:"4A")
jack!.apartment = room
room!.tenant = jack
jack = nil
// room = nil
- 無主引用示例
//適用于無主引用的場景 unowned
//無主引用永遠(yuǎn)都是有值的
//CerditCard 中的 customer 為無主引用 當(dāng)customer為空(john=nil)時(shí) 不在有對(duì)CerditCard的引用 因此CerdutCard也釋放了
class CerditCard{
let number: UInt64
unowned let customer: Customer
init(number: UInt64, customer: Customer){self.number = number;self.customer = customer
}
deinit {print("CerditCard is being deinitialized")}
}
class Customer{
let name:String
var card: CerditCard?
init(name: String){self.name = name}
deinit{ print("Customer is being deinitialized")}
}
var john:Customer?
john = Customer(name:"john")
john!.card = CerditCard(number: 1234_5678_9012_3456, customer: john!)
john = nil
- 閉包當(dāng)中避免循環(huán)引用
class HTMLElement{
let name: String
let text: String?
lazy var asHTML: Void -> String = {[unowned self] in
if let text = self.text{return "<\(self.name)>\(text)</\(self.name)>"}else{return "<\(self.name)/>"}
}
init (name: String, text: String){self.name = name
self.text = text
}
deinit{print("HTMLElement is being deinitialized")}
}
var paragraph: HTMLElement? = HTMLElement(name:"p", text:"hello world!")
print(paragraph!.asHTML())
paragraph = nil
在閉包和捕獲實(shí)例總是互相引用并且總是同時(shí)銷毀的 將閉包內(nèi)的捕獲定義為無主引用 相反 閉包內(nèi)的捕獲可能先銷毀的 應(yīng)該使用弱引用
- 使用
reduce
組合數(shù)組元素
let result = selectedSubjects.reduce("", combine: { (tempResult, element) -> String in return tempResult + " " + element})
- 錯(cuò)誤處理官方示例代碼
enum VendingMachineError: ErrorType{
case InvalidSelection //選擇無效
case InsufficientFuncs(coinsNeeded: Int) //金額不足
case OutOfStock //缺貨
}
struct Item {
var price: Int
var count: Int
}
class VendingMachine{
var inventory = [
"Candy Bar": Item(price: 12, count: 7),
"Chips": Item(price: 10, count: 10),
"Pretzels": Item(price: 7, count: 11)
]
var coinsDeposited = 0
func dispenseSnack(snack: String){
print("Dispensing \(snack)")
}
func vend(itemName name: String) throws{
guard var item = inventory[name] else{throw VendingMachineError.InvalidSelection}
guard item.count > 0 else{
throw VendingMachineError.OutOfStock}
guard item.price <= coinsDeposited else{throw VendingMachineError.InsufficientFuncs(coinsNeeded: item.price - coinsDeposited)}
coinsDeposited -= item.price
item.count -= 1
inventory[name] = item
dispenseSnack(name)
}
}
let favoriteSnacks = [
"Alice": "Chips",
"Bob": "Licorice",
"Eve": "Pretzels"
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws{
let snackName = favoriteSnacks[person] ?? "Candy Bar" //空合運(yùn)算符
try vendingMachine.vend(itemName: snackName)
}
var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do{
try buyFavoriteSnack("Alice", vendingMachine: vendingMachine)
}catch VendingMachineError.InvalidSelection{
print("Invalid Selection")
}catch VendingMachineError.OutOfStock{
print("out of stock.")
}catch VendingMachineError.InsufficientFuncs(let coinsNeeded){
print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")
}
- 嵌套類型示例代碼
struct BlackjackCard {
enum Suit: Character{
case Spades = "??", Hearts = "??", Diamonds = "??", Clubs = "??"
}
enum Rank: Int{
case Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King, Ace
struct Values{
let first: Int, second: Int?}
var values: Values{
switch self {
case Ace:
return Values(first: 1, second: 11)
case Jack, Queen, King:
return Values(first: 10, second: nil)
default:return Values(first: self.rawValue, second: nil)
}}
}
let rank: Rank, suit: Suit
var description: String{
var output = "suit is \(suit.rawValue),"
output += "value is \(rank.values.first) "
if let second = rank.values.second{
output += "or \(second)"
}
return output
}
}
let theAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades)
print("theAceOfSpades:\(theAceOfSpades.description)")