官术网_书友最值得收藏!

There's more...

We've seen how we can store closures, but we can also use them as method parameters. This pattern can be really useful when we want to be notified when a long-running task is completed.

Let's imagine that we want to save the details of our person object to a remote database, maybe for backup or use on other devices. We'll amend our Person class to include this save functionality, and in the process, see how we can pass in a closure, store it, and execute it at a later time.

Add the following code to our Person class:

class Person { 
//....
var saveHandler: ((Bool) -> Void)?

func saveToRemoteDatabase(handler: @escaping (Bool) -> Void) {
saveHandler = handler
// Send person information to remove database
// Once remote save is complete, it calls saveComplete(Bool)
}

func saveComplete(success: Bool) {
saveHandler?(success)
}
}

We define an optional variable to hold onto the save handler during the long-running save operation. Our closure will take a Bool to indicate whether the save was a success:

var saveHandler: ((Bool) -> Void)? 

Let's define a method to save our Person object, which takes a closure as a parameter:

func saveToRemoteDatabase(handler: @escaping (Bool) -> Void) { 
saveHandler = handler
// Send person information to remove database
// Once remote save is complete, it calls saveComplete(Bool)
}

Our function stores the given closure in the variable, and then starts the process to save to the remote database (the actual implementation of this is outside the scope of this recipe). This save process will call the saveComplete method when completed. We added a modifier, @escaping, just before the closure type definition. This tells the compiler that, rather than using the closure within this method, we intend to store the closure and use it later. The closure will be escaping the scope of this method. This modifier is needed to prevent the compiler from doing certain optimizations that would be possible if the closure was nonescaping.

With the save operation complete, we can execute the saveHandler variable, passing in the success boolean. However, since we stored the closure as optional, we need to unwrap it by adding a ? after the variable name. If saveHandler has a value, the closure will be executed; if it is nil, the expression is ignored:

func saveComplete(success: Bool) { 
saveHandler?(success)
}

Now that we have a function that takes a closure, let's see how we call it:

let dave = createPerson("David", "Ernest", "Moon") 
dave.saveToRemoteDatabase(handler: { success in
print("Saved finished. Successful: \(success))")
})

Swift provides a more concise way to provide closures to functions. When a closure is the last (or only) parameter, Swift allows it to be provided as a trailing closure--that is, the parameter name can be dropped and the closure can be specified after the parameter brackets. So we can, instead, do the following:

dave.saveToRemoteDatabase { success in 
print("Saved finished. Successful: \(success))")
}
主站蜘蛛池模板: 阿拉尔市| 东明县| 永善县| 祁门县| 泰来县| 西丰县| 长沙市| 响水县| 老河口市| 婺源县| 灵璧县| 图木舒克市| 三亚市| 彩票| 新宁县| 铁力市| 布拖县| 阿鲁科尔沁旗| 高陵县| 嘉兴市| 龙陵县| 湟源县| 昌乐县| 丰顺县| 三原县| 德清县| 永康市| 福州市| 准格尔旗| 苍梧县| 惠水县| 蒲江县| 萨迦县| 平利县| 司法| 汉沽区| 清河县| 九龙城区| 侯马市| 安泽县| 西充县|