本文是學(xué)習(xí)《The Swift Programming Language》整理的相關(guān)隨筆,基本的語法不作介紹,主要介紹Swift中的一些特性或者與OC差異點(diǎn)。
系列文章:
Closures
閉包表達(dá)式語法(Closure Expression Syntax)
Closure expression syntax has the following general form:
{ (parameters) -> return type in
statements
}
例子:數(shù)組排序的例子
var names:[String] = ["B","A","C"];
names = names.sorted(by: {
(num1:String,num2:String) -> Bool in
return num1 < num2;
});
print(names);
執(zhí)行結(jié)果:
["A", "B", "C"]
上下文檢測(cè)類型(Inferring Type From Context)
Because the sorting closure is passed as an argument to a
method, Swift can infer the types of its parameters and
the type of the value it returns. The sorted(by:) method
is being called on an array of strings, so its argument
must be a function of type (String, String) -> Bool. This
means that the (String, String) and Bool types do not need
to be written as part of the closure expression’s
definition.
- 排序的閉包因?yàn)镾wift中的類型檢測(cè)機(jī)制,所以可以省掉寫入String,-> Bool
針對(duì)上述的例子做簡(jiǎn)化:
var names:[String] = ["B","A","C"];
names = names.sorted(by: {
(name1,name2) in
return name1 < name2;
});
print(names);
單表達(dá)式閉包的隱式返回(Implicit Returns from Single-Expression Closures)
Single-expression closures can implicitly return the
result of their single expression by omitting the return
keyword from their declaration
- 單表達(dá)式的閉包可以省略掉return關(guān)鍵字
繼續(xù)簡(jiǎn)化上述例子:
var names:[String] = ["B","A","C"];
names = names.sorted(by: {
(name1,name2) in name1 < name2;
});
print(names);
參數(shù)名稱縮寫(Shorthand Argument Names)
Swift automatically provides shorthand argument names to inline closures, which can be used to refer to the values of the closure’s arguments by the names $0, $1, $2, and so on.
- 結(jié)合閉包中類型的檢測(cè),閉包中的參數(shù)名可以使用$0, $1, $2代替
繼續(xù)簡(jiǎn)化上述例子:
var names:[String] = ["B","A","C"];
names = names.sorted(by: {
$0 < $1;
});
print(names);
操作方法(Operator Methods)
There’s actually an even shorter way to write the closure
expression above. Swift’s String type defines its string-
specific implementation of the greater-than operator (>)
as a method that has two parameters of type String, and
returns a value of type Bool.
- 繼續(xù)簡(jiǎn)化可以直接用
>,<表示比較結(jié)果
繼續(xù)簡(jiǎn)化例子:
var names:[String] = ["B","A","C"];
names = names.sorted(by:<);
print(names);
尾隨閉包(Trailing Closures)
If you need to pass a closure expression to a function as
the function’s final argument and the closure expression
is long, it can be useful to write it as a trailing
closure instead. A trailing closure is written after the
function call’s parentheses, even though it is still an
argument to the function. When you use the trailing
closure syntax, you don’t write the argument label for the
closure as part of the function call.
- 當(dāng)閉包是函數(shù)中的最后一個(gè)參數(shù)時(shí),函數(shù)調(diào)用可以省略掉參數(shù)標(biāo)簽的寫法,簡(jiǎn)化函數(shù)
閉包是引用類型數(shù)據(jù)(Closures Are Reference Types)
In the example above, incrementBySeven and incrementByTen
are constants, but the closures these constants refer to
are still able to increment the runningTotal variables
that they have captured. This is because functions and
closures are reference types.
- Swift中的閉包是引用類型的數(shù)據(jù)
例子:
var num = 0;
func increment(completion:() -> Void){
completion();
print("num:\(num)");
}
increment {
num += 10;
}
let referIncrement = increment;
referIncrement{
num += 20;
}
執(zhí)行結(jié)果:
num:10
num:30
逃逸閉包(Escaping Closures)
A closure is said to escape a function when the closure is
passed as an argument to the function, but is called after
the function returns. When you declare a function that
takes a closure as one of its parameters, you can write
@escaping before the parameter’s type to indicate that the
closure is allowed to escape.
- Swift中如果需要逃逸閉包需要利用關(guān)鍵字
@escaping修飾
例子:
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure(completionHandler: {
self.x = 100;
});
someFunctionWithNonescapingClosure(closure: {
x = 200;
});
// 以下的調(diào)用方式一樣可行,同時(shí)說明了尾隨閉包的使用
//someFunctionWithEscapingClosure { self.x = 100 }
//someFunctionWithNonescapingClosure { x = 200 }
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
completionHandlers.first?()
print(instance.x)
執(zhí)行結(jié)果:
200
100
自動(dòng)閉包(Autoclosures)
An autoclosure is a closure that is automatically created
to wrap an expression that’s being passed as an argument
to a function. It doesn’t take any arguments, and when
it’s called, it returns the value of the expression that’s
wrapped inside of it.
- Swift中的自動(dòng)閉包能動(dòng)態(tài)的封裝一個(gè)表達(dá)式為一個(gè)函數(shù)的參數(shù),自動(dòng)閉包不能帶任何的參數(shù)
例子:
var num = 1;
func filter(contions:() -> Bool){
if contions(){
num += 3;
print("num:\(num)");
}else{
num += 1;
print("num:\(num)");
filter(contions: {num % 3 == 0})
}
}
filter(contions: { num % 3 == 0 })
執(zhí)行結(jié)果:
num:2
num:3
num:6
下面開始利用@autoclosure簡(jiǎn)化:
var num = 1;
func filter(_ contions: @autoclosure () -> Bool){
if contions(){
num += 3;
print("num:\(num)");
}else{
num += 1;
print("num:\(num)");
filter(num % 3 == 0)
}
}
filter(num % 3 == 0)
Overusing autoclosures can make your code hard to
understand. The context and function name should make it
clear that evaluation is being deferred.
- autoclosure的過度使用并不好,會(huì)讓代碼邏輯看起來更難理解,必須了解上下文中函數(shù)的定義才可結(jié)合使用