-
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")
}
- 空合运算符(
Nil Coalescing Operator
)
var a:Int?
let b:Int = 10
let c = a ?? b
print("c = \(c)")
ps.以上代码类似
c = a != nil ?a! :b
但看起来更加优雅
- 区间运算符
for i in 1...5{
print("\(i) ")
}
for i in 1..<5{
print("\(i) ")
}
swift
中并没有左开右闭区间
- 字符串的
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) ")
}
- 可变参数
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))")
- 函数类型
func addTwoInts(a:Int, b:Int) -> Int{
return a + b
}
var mathFunction:(Int,Int) -> Int = addTwoInts
print("\(mathFunction(3,4))")
- 函数作为参数类型
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)
- 函数作为返回类型
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 是一个函数类型
let f1 = chooseStepFunction(true)
print("f1 = \(f1(3))")
- 嵌套函数
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 是一个函数类型
let f1 = chooseStepFunction(true)
print("f1 = \(f1(3))")
- 闭包
sort
为swift
标准库提供的方法 可以根据提供的排序规则对一个数组进行排序 生成一个长度一致的新数组
以下使用了闭包表达式和函数方式 实现了排序
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)")
因为sort
方法 明确定义了闭包的参数 返回值所以可以进一步简写为
names.sort{s1,s2 in s1 > s2}
可以使用$0 $1 $2
顺序表示闭包的参数 所以可以再简写为
names.sort({$0 > $1})
swift
中的String
类型 定义了“>”的字符串实现 因此还可以简写为
names.sort(>)
不过 最好使用完整的闭包表达式 使代码更具有更好的可读性
- 尾随闭包
可以将一个闭包表达式作为函数的最后一个参数传入来增强函数的可读性
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)")
- 非逃逸闭包 自动闭包
这个现在看懂了
@escaping
逃逸闭包指的是闭包在函数返回后才执行
@noescaping
则相反 在函数返回之前就执行了
@autoclosure
指的是自动创建的闭包,不能接受参数,并且属于非逃逸闭包 下边是一个自动闭包的例子,
func printIfTrue(@autoclosure predicate: ()-> Bool){
if predicate(){
print("the result is true")
}
}
printIfTrue(2 > 1)
//直接进行调用了,Swift 将会把 2 > 1 这个表达式自动转换为 () -> Bool。这样我们就得到了一个写法简单,表意清楚的式子。
- 递归枚举求值
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))")
- 下标脚本
struct TimeTable {
let multiplier:Int
subscript(index:Int) -> Int {return multiplier * index}
}
let threeTimesTable = TimeTable(multiplier:3)
print("\(threeTimesTable[6])")
- 弱引用示例
//适用于弱引用的场景 weak
//公寓和人 room对jack的引用为弱引用 jack为nil之后 room并不会为nil 但jack不会对room产生强引用 room为nil 会释放其所占内存空间 并不会因为jack的引用而不释放
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
//无主引用永远都是有值的
//CerditCard 中的 customer 为无主引用 当customer为空(john=nil)时 不在有对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
- 闭包当中避免循环引用
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
在闭包和捕获实例总是互相引用并且总是同时销毁的 将闭包内的捕获定义为无主引用 相反 闭包内的捕获可能先销毁的 应该使用弱引用
- 使用
reduce
组合数组元素
let result = selectedSubjects.reduce("", combine: { (tempResult, element) -> String in return tempResult + " " + element})
- 错误处理官方示例代码
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" //空合运算符
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)")