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
}
如何贡献?
我们希望让对这个项目的贡献尽可能简单、透明。请参阅贡献指南。