Skip to content

Commit 46ee60c

Browse files
author
Jiaolong
committed
feat: finished 100%
1 parent 9c8a28d commit 46ee60c

File tree

1 file changed

+40
-139
lines changed

1 file changed

+40
-139
lines changed

swift-6-beta.docc/LanguageGuide/Closures.md

Lines changed: 40 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -611,23 +611,13 @@ incrementByTen()
611611

612612
> 注意:如果将闭包赋值给类实例的属性,并且闭包通过引用实例或其成员来捕获该实例,则将在闭包和实例之间创建一个强引用循环。Swift 使用_捕获列表_来打破这些强引用循环。有关更多信息,请参阅 <doc:AutomaticReferenceCounting#Strong-Reference-Cycles-for-Closures>.
613613
614-
## Closures Are Reference Types
614+
## 闭包是引用类型
615615

616-
In the example above,
617-
`incrementBySeven` and `incrementByTen` are constants,
618-
but the closures these constants refer to are still able to increment
619-
the `runningTotal` variables that they have captured.
620-
This is because functions and closures are *reference types*.
616+
在上面的示例中,`incrementBySeven``incrementByTen` 是常量,但这些常量引用的闭包仍然能够递增它们捕获的 `runningTotal` 变量。这是因为函数和闭包是*引用类型*
621617

622-
Whenever you assign a function or a closure to a constant or a variable,
623-
you are actually setting that constant or variable to be
624-
a *reference* to the function or closure.
625-
In the example above,
626-
it's the choice of closure that `incrementByTen` *refers to* that's constant,
627-
and not the contents of the closure itself.
618+
每当你将函数或闭包赋值给一个常量或变量时,你实际上是在将该常量或变量设置为对函数或闭包的*引用*。在上面的示例中,`incrementByTen` *引用*的闭包选择是常量,而不是闭包本身的内容。
628619

629-
This also means that if you assign a closure to two different constants or variables,
630-
both of those constants or variables refer to the same closure.
620+
这也意味着,如果将闭包分配给两个不同的常量或变量,则这两个常量或变量都引用同一闭包。
631621

632622
```swift
633623
let alsoIncrementByTen = incrementByTen
@@ -660,24 +650,15 @@ is the same as calling `incrementByTen`.
660650
Because both of them refer to the same closure,
661651
they both increment and return the same running total.
662652

663-
## Escaping Closures
664-
665-
A closure is said to *escape* a function
666-
when the closure is passed as an argument to the function,
667-
but is called after the function returns.
668-
When you declare a function that takes a closure as one of its parameters,
669-
you can write `@escaping` before the parameter's type
670-
to indicate that the closure is allowed to escape.
671-
672-
One way that a closure can escape
673-
is by being stored in a variable that's defined outside the function.
674-
As an example,
675-
many functions that start an asynchronous operation
676-
take a closure argument as a completion handler.
677-
The function returns after it starts the operation,
678-
but the closure isn't called until the operation is completed ---
679-
the closure needs to escape, to be called later.
680-
For example:
653+
上面的示例表明,调用 `alsoIncrementByTen` 与调用 `incrementByTen` 相同。由于它们都引用相同的闭包,因此它们都会递增并返回相同的 runningTotal 值。
654+
655+
## 逃逸闭包
656+
657+
当一个闭包作为参数传到一个函数中,我们称该闭包从函数中逃逸。当你定义接受闭包作为参数的函数时,你可以在参数名之前标注 @escaping,用来指明这个闭包是允许“逃逸”出这个函数的。
658+
659+
当闭包作为参数传递给函数,但是这个闭包在函数返回之后才被执行,该闭包被称为*逃逸*函数。当你声明一个将闭包作为其参数之一的函数时,你可以在参数的类型之前写入 `@escaping`,以表示这个闭包是允许逃逸的。
660+
661+
闭包可以逃逸的一种方式是存储在函数外部定义的变量中。例如,许多启动异步操作的函数将闭包参数作为 completion handler。该函数在启动操作后返回,但在操作完成之前不会调用闭包,这种情况下闭包需要逃逸,以便在之后调用。例如:
681662

682663
```swift
683664
var completionHandlers: [() -> Void] = []
@@ -697,31 +678,13 @@ func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
697678
```
698679
-->
699680

700-
The `someFunctionWithEscapingClosure(_:)` function takes a closure as its argument
701-
and adds it to an array that's declared outside the function.
702-
If you didn't mark the parameter of this function with `@escaping`,
703-
you would get a compile-time error.
704-
705-
An escaping closure that refers to `self`
706-
needs special consideration if `self` refers to an instance of a class.
707-
Capturing `self` in an escaping closure
708-
makes it easy to accidentally create a strong reference cycle.
709-
For information about reference cycles,
710-
see <doc:AutomaticReferenceCounting>.
711-
712-
Normally, a closure captures variables implicitly
713-
by using them in the body of the closure,
714-
but in this case you need to be explicit.
715-
If you want to capture `self`,
716-
write `self` explicitly when you use it,
717-
or include `self` in the closure's capture list.
718-
Writing `self` explicitly lets you express your intent,
719-
and reminds you to confirm that there isn't a reference cycle.
720-
For example, in the code below,
721-
the closure passed to `someFunctionWithEscapingClosure(_:)`
722-
refers to `self` explicitly.
723-
In contrast, the closure passed to `someFunctionWithNonescapingClosure(_:)`
724-
is a nonescaping closure, which means it can refer to `self` implicitly.
681+
`someFunctionWithEscapingClosure(_:)` 函数将闭包作为其参数,并将其添加到函数外部声明的数组中。如果不用 `@escaping` 标记此函数的参数,则会收到编译错误。
682+
683+
684+
如果 `self` 引用类的实例,则引用 `self` 的逃逸闭包需要特别考虑。在逃逸闭合中捕获 `self`,很容易意外地创建一个强循环引用。有关参考循环引用的信息,请参阅 [doc:AutomaticReferenceCounting](doc:AutomaticReferenceCounting)
685+
686+
通常,闭包通过在闭包主体中使用变量来隐式捕获变量,但在这种情况下,您需要明确。如果要捕获 `self`,请在使用它时显式写入 `self`,或者在闭包的捕获列表中包含 `self`。明确的写出 `self` 更能表达你的意图,并提醒你确认没有产生循环引用。例如,在下面的代码中,传递给 `someFunctionWithEscapingClosure(_:)` 的闭包显式引用 `self`。相比之下,传递给 `someFunctionWithNonescapingClosure(_:)` 的闭包是非逃逸闭包,这意味着它可以隐式引用 `self`
687+
725688

726689
```swift
727690
func someFunctionWithNonescapingClosure(closure: () -> Void) {
@@ -773,9 +736,7 @@ print(instance.x)
773736
```
774737
-->
775738

776-
Here's a version of `doSomething()` that captures `self`
777-
by including it in the closure's capture list,
778-
and then refers to `self` implicitly:
739+
这是 `doSomething()` 的一个版本,它通过将 `self` 包含在闭包的捕获列表中来捕获 `self`,然后隐式引用 `self`
779740

780741
```swift
781742
class SomeOtherClass {
@@ -809,13 +770,7 @@ class SomeOtherClass {
809770
```
810771
-->
811772

812-
If `self` is an instance of a structure or an enumeration,
813-
you can always refer to `self` implicitly.
814-
However,
815-
an escaping closure can't capture a mutable reference to `self`
816-
when `self` is an instance of a structure or an enumeration.
817-
Structures and enumerations don’t allow shared mutability,
818-
as discussed in <doc:ClassesAndStructures#Structures-and-Enumerations-Are-Value-Types>.
773+
如果 `self` 是结构体或枚举的实例,则始终可以隐式引用 `self`。但是转义闭包无法捕获其对 `self` 的可变引用。结构体和枚举不允许共享可变性,如 <doc:ClassesAndStructures#Structures-and-Enumerations-Are-Value-Types> 中所述。
819774

820775
```swift
821776
struct SomeStruct {
@@ -854,12 +809,7 @@ struct SomeStruct {
854809
```
855810
-->
856811

857-
The call to the `someFunctionWithEscapingClosure` function
858-
in the example above is an error
859-
because it's inside a mutating method,
860-
so `self` is mutable.
861-
That violates the rule that escaping closures can't capture
862-
a mutable reference to `self` for structures.
812+
在上面的示例中,对 `someFunctionWithEscapingClosure` 函数的调用是一个错误,因为它位于一个可变函数中,因此 `self` 是可变的。这违反了规则,即转义闭包不能捕获对结构的 `self` 的可变引用。
863813

864814
<!--
865815
- test: `noescape-closure-as-argument`
@@ -901,30 +851,13 @@ a mutable reference to `self` for structures.
901851
```
902852
-->
903853

904-
## Autoclosures
905-
906-
An *autoclosure* is a closure that's automatically created
907-
to wrap an expression that's being passed as an argument to a function.
908-
It doesn't take any arguments,
909-
and when it's called, it returns the value
910-
of the expression that's wrapped inside of it.
911-
This syntactic convenience lets you omit braces around a function's parameter
912-
by writing a normal expression instead of an explicit closure.
913-
914-
It's common to *call* functions that take autoclosures,
915-
but it's not common to *implement* that kind of function.
916-
For example,
917-
the `assert(condition:message:file:line:)` function
918-
takes an autoclosure for its `condition` and `message` parameters;
919-
its `condition` parameter is evaluated only in debug builds
920-
and its `message` parameter is evaluated only if `condition` is `false`.
921-
922-
An autoclosure lets you delay evaluation,
923-
because the code inside isn't run until you call the closure.
924-
Delaying evaluation is useful for code
925-
that has side effects or is computationally expensive,
926-
because it lets you control when that code is evaluated.
927-
The code below shows how a closure delays evaluation.
854+
## 自动闭包
855+
856+
*自动闭包*是一种自动创建的闭包,用于包装作为参数传递给函数的表达式。它不接受任何参数,当它被调用时,它返回包裹在其内部的表达式的值。这种便利语法让你能够省略闭包的大括号,用一个普通的表达式来代替显式的闭包。
857+
858+
我们经常会*调用*采用自动闭包的函数,但是很少去*实现*这样的函数。例如,`assert(condition:message:file:line:)` 函数接受自动闭包作为它的 `condition``message` 参数; 其 `condition` 参数仅在 Debug 版本中计算,而其 `message` 参数仅在 `condition``false` 时计算。
859+
860+
自动闭包允许您延迟计算,因为在你调用这个闭包之前,内部代码不会运行。延迟计算对于有副作用或高计算成本的代码非常有用,因为它使得你能控制代码的执行时机。下面的代码展示了闭包如何延时计算。
928861

929862
```swift
930863
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
@@ -974,18 +907,9 @@ print(customersInLine.count)
974907
TODO: It may be worth describing the differences between ``lazy`` and autoclousures.
975908
-->
976909

977-
Even though the first element of the `customersInLine` array is removed
978-
by the code inside the closure,
979-
the array element isn't removed until the closure is actually called.
980-
If the closure is never called,
981-
the expression inside the closure is never evaluated,
982-
which means the array element is never removed.
983-
Note that the type of `customerProvider` isn't `String`
984-
but `() -> String` ---
985-
a function with no parameters that returns a string.
910+
即使 `customersInLine` 数组的第一个元素被闭包内的代码删除,但在实际调用闭包之前,不会删除数组中的元素。如果从不调用闭包,则永远不会计算闭包内的表达式,这意味着永远不会删除数组元素。请注意,`customerProvider` 的类型不是 `String`,而是 `() -> String` --- 一个返回字符串的没有参数的函数。
986911

987-
You get the same behavior of delayed evaluation
988-
when you pass a closure as an argument to a function.
912+
将闭包作为参数传递给函数时,你能获得同样的延时计算行为。
989913

990914
```swift
991915
// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
@@ -1011,17 +935,7 @@ serve(customer: { customersInLine.remove(at: 0) } )
1011935
```
1012936
-->
1013937

1014-
The `serve(customer:)` function in the listing above
1015-
takes an explicit closure that returns a customer's name.
1016-
The version of `serve(customer:)` below
1017-
performs the same operation but, instead of taking an explicit closure,
1018-
it takes an autoclosure
1019-
by marking its parameter's type with the `@autoclosure` attribute.
1020-
Now you can call the function
1021-
as if it took a `String` argument instead of a closure.
1022-
The argument is automatically converted to a closure,
1023-
because the `customerProvider` parameter's type is marked
1024-
with the `@autoclosure` attribute.
938+
上面列表中的 `serve(customer:)` 函数采用显式闭包,返回客户的名称。下面的 `serve(customer:)` 版本执行相同的操作,但是,它不是采用显式闭包,而是通过使用 `@autoclosure` 属性标记其参数的类型来进行自动闭合。现在,您可以调用该函数,就好像它采用 `String` 参数而不是闭包一样。该参数会自动转换为闭包,因为 `customerProvider` 参数的类型用 `@autoclosure` 属性标记。
1025939

1026940
```swift
1027941
// customersInLine is ["Ewa", "Barry", "Daniella"]
@@ -1047,13 +961,9 @@ serve(customer: customersInLine.remove(at: 0))
1047961
```
1048962
-->
1049963

1050-
> Note: Overusing autoclosures can make your code hard to understand.
1051-
> The context and function name should make it clear
1052-
> that evaluation is being deferred.
964+
> 注意:过度使用自动闭包可能会使您的代码难以理解。上下文和函数名称应明确表示计算正在被推迟。
1053965
1054-
If you want an autoclosure that's allowed to escape,
1055-
use both the `@autoclosure` and `@escaping` attributes.
1056-
The `@escaping` attribute is described above in <doc:Closures#Escaping-Closures>.
966+
如果您想要允许一个自动闭包可以逃逸,请同时使用 `@autoclosure``@escaping` 属性。`@escaping` 属性在上面的 <doc:Closures#Escaping-Closures> 中进行了描述。
1057967

1058968
```swift
1059969
// customersInLine is ["Barry", "Daniella"]
@@ -1097,22 +1007,13 @@ for customerProvider in customerProviders {
10971007
```
10981008
-->
10991009

1100-
In the code above,
1101-
instead of calling the closure passed to it
1102-
as its `customerProvider` argument,
1103-
the `collectCustomerProviders(_:)` function
1104-
appends the closure to the `customerProviders` array.
1105-
The array is declared outside the scope of the function,
1106-
which means the closures in the array can be executed after the function returns.
1107-
As a result,
1108-
the value of the `customerProvider` argument
1109-
must be allowed to escape the function's scope.
1110-
1111-
> Beta Software:
1010+
在上面的代码中,`collectCustomerProviders(_:)` 函数将闭包追加到 `customerProviders` 数组中,而不是调用作为其 `customerProvider` 参数传递给它的闭包。数组是在函数的作用域之外声明的,这意味着数组中的闭包可以在函数返回后执行。因此 `customerProvider` 参数必须允许逃逸出函数的作用域。
1011+
1012+
> 测试版软件:
11121013
>
1113-
> This documentation contains preliminary information about an API or technology in development. This information is subject to change, and software implemented according to this documentation should be tested with final operating system software.
1014+
> 本文档包含有关正在开发的 API 或技术的初步信息。此信息可能会发生变化,根据本文档实施的软件应使用最终操作系统软件进行测试。
11141015
>
1115-
> Learn more about using [Apple's beta software](https://developer.apple.com/support/beta-software/).
1016+
> 了解有关使用 [Apple 测试版软件](https://developer.apple.com/support/beta-software/) 的更多信息.
11161017
11171018
<!--
11181019
This source file is part of the Swift.org open source project

0 commit comments

Comments
 (0)