Swift 中的 Bolts
Bolts 是一系列设计用于简化移动应用开发的底层库。Bolts 由 Parse 和 Facebook 为我们自己的内部使用而设计,我们决定开源这些库,以便让其他人可以使用它们。
Task
Bolts Task 是 iOS/OS X/watchOS/tvOS 以及任何支持 Swift 的平台上的 futures/promises 的完整实现。Task 代表异步操作的结果,这通常是从函数返回的。除了能够有不同状态 completed/faulted/cancelled 外,它们还提供以下好处
task消耗的系统资源更少,因为它们在等待其他task时不会占用线程。task可以顺序执行,这将不会像仅使用回调时那样创建嵌套的“金字塔”代码。task是完全可组合的,允许你执行分支、并行处理和复杂的错误处理,而无需像有许多命名的回调那样编写面条代码。task允许你按照代码执行的顺序来排列代码,而无需将你的逻辑分散到各个回调函数中。task不依赖于任何特定的线程模型。因此,你可以使用像操作队列/dispatch队列或者线程执行器这样的概念。task可以同步或异步使用,提供任何函数/操作的相同结果的好处。
开始吧
将以下行添加到您的Podfile中
pod 'Bolts-Swift'运行pod install,您现在应该已经安装了最新的Parse版本。
将以下行添加到您的Cartfile中
github "BoltsFramework/Bolts-Swift"
运行carthage update,您现在应该已经拥有了Carthage文件夹中的最新版本的Bolts。
-
作为子项目使用Bolts
您还可以将Bolts作为子项目包含在您的应用程序中,尽管我们不推荐这样做,因为它将显著增加您的索引时间。要这样做,只需将
BoltsSwift.xcodeproj文件拖放到您的工作区即可。 -
导入Bolts
现在您已经将框架链接到您的应用程序,请在您想要使用Bolts的所有
.swift文件中添加以下行import BoltsSwift
链式任务
您可以在任务上调用某些特殊方法,这些方法接受一个闭包参数并将返回任务对象。因为它们返回任务,这意味着您可以在阶段执行中继续调用这些方法(也称为链式操作)以执行逻辑。这是一种强大的方法,使您的代码看起来像一系列步骤,同时利用异步执行的力量。以下是您应该了解的3个关键函数。
- 使用
continueWith在任务运行后检查任务,并使用结果执行更多操作 - 使用
continueWithTask根据前一个任务的结果添加更多工作 - 使用
continueOnSuccessWith只有在任务无错误执行时执行逻辑
有关可用方法的完整列表,请参阅源代码中的文件 Task+ContinueWith.swift
continueWith
每个Task都有一个名为continueWith的函数,它接受一个延续闭包。一旦任务完成,就会执行延续。您可以使用延续检查任务是否成功以及获取其结果。
save(object).continueWith { task in
if task.cancelled {
// Save was cancelled
} else if task.faulted {
// Save failed
} else {
// Object was successfully saved
let result = task.result
}
}在成功后继续
在许多情况下,您只有在前面的任务成功的情况下才想要做更多的工作,并且将任何错误或取消传播给稍后处理。为此,请使用continueOnSuccessWith函数
save(object).continueOnSuccessWith { result in
// Closure receives the result of a succesfully performed task
// If result is invalid throw an error which will mark task as faulted
}内部,continueOnSuccessWith函数调用continueOnSuccessWithTask方法,这在需要生成额外工作的场景中更强大、更有用。
continueOnSuccessWithTask
如您在上面所见,如果您从continueWith函数返回一个对象,它将成为Task的结果。但是如果有更多工作要做呢?如果您想调用更多任务并返回它们的结果,则可以使用continueWithTask。这为您提供了将更多异步工作链式连接的能力。
在下面的示例中,我们希望获取一个用户配置文件,然后获取配置文件图像,如果这些操作中的任何一个失败,我们还希望显示一个占位符图像
fetchProfile(user).continueOnSuccessWithTask { task in
return fetchProfileImage(task.result);
}.continueWith { task in
if let image = task.result {
return image
}
return ProfileImagePlaceholder()
}创建任务
要创建任务,您需要一个TaskCompletionSource,它是任何Task的消费者端,它允许您控制任务是否完成、错误或取消。创建TaskCompletionSource后,您需要调用setResult()/setError()/cancel()来触发其延续并改变其状态。
func fetch(object: PFObject) -> Task<PFObject> {
let taskCompletionSource = TaskCompletionSource<PFObject>()
object.fetchInBackgroundWithBlock() { (object: PFObject?, error: NSError?) in
if let error = error {
taskCompletionSource.setError(error)
} else if let object = object {
taskCompletionSource.setResult(object)
} else {
taskCompletionSource.cancel()
}
}
return taskCompletionSource.task
}并行任务
您还可以并行执行多个任务,并使用whenAll()函数链式连接它们的结果。
let query = PFQuery(className: "Comments")
find(query).continueWithTask { task in
var tasks: [Task<PFObject>] = []
task.result?.forEach { comment in
tasks.append(self.deleteComment(comment))
}
return Task.whenAll(tasks)
}.continueOnSuccessWith { task in
// All comments were deleted
}任务执行者
函数continueWith()和continueWithTask()都接受一个可选的执行器参数。这允许您控制如何执行后续闭包。默认执行器会将任务分发给全局分发队列,但您可以提供自己的执行器以按特定方式进行工作调度。例如,如果您想在主线程上继续工作
fetch(object).continueWith(Executor.mainThread) { task in
// This closure will be executor on the main application's thread
}如何贡献?
我们希望让对这个项目的贡献尽可能简单、透明。请参阅贡献指南。