Swift

Swift4 基础部分:Closures

2017-07-23  本文已影响1204人  Arnold134777

本文是学习《The Swift Programming Language》整理的相关随笔,基本的语法不作介绍,主要介绍Swift中的一些特性或者与OC差异点。

系列文章:

Closures

闭包表达式语法(Closure Expression Syntax)

Closure expression syntax has the following general form:

 { (parameters) -> return type in
    statements
}

例子:数组排序的例子

var names:[String] = ["B","A","C"];
names = names.sorted(by: {
    (num1:String,num2:String) -> Bool in
    return num1 < num2;
});
print(names);

执行结果:

["A", "B", "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.

针对上述的例子做简化:

var names:[String] = ["B","A","C"];
names = names.sorted(by: {
    (name1,name2) in
    return name1 < name2;
});
print(names);

单表达式闭包的隐式返回(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

继续简化上述例子:

var names:[String] = ["B","A","C"];
names = names.sorted(by: {
    (name1,name2) in name1 < name2;
});
print(names);

参数名称缩写(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.

继续简化上述例子:

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.

继续简化例子:

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.

闭包是引用类型数据(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.

例子:

var num = 0;
func increment(completion:() -> Void){
    completion();
    print("num:\(num)");
}
increment {
    num += 10;
}
let referIncrement = increment;
referIncrement{
    num += 20;
}

执行结果:

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.

例子:

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;
        });
        
        // 以下的调用方式一样可行,同时说明了尾随闭包的使用
        //someFunctionWithEscapingClosure { self.x = 100 }
        //someFunctionWithNonescapingClosure { x = 200 }
    }
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
completionHandlers.first?()
print(instance.x)

执行结果:

200
100

自动闭包(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.

例子:


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 })

执行结果:

num:2
num:3
num:6

下面开始利用@autoclosure简化:

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.
上一篇 下一篇

猜你喜欢

热点阅读