```css
```css
class test112: NSObject {
enum MErr:Error{
case serverError(String)
}
/*
withCheckedContinuation 是 Swift 并发模型中的一个重要工具,它允许你将异步操作转换为一个暂停的函数,直到你手动恢复它。它在将传统的回调式异步代码转换为 async/await 风格时非常有用
确保调用 continuation.resume 来恢复函数,避免内存泄漏或程序挂起
*/
func fetchDatas() async ->String{
//<T, Never>
let ret1 = await withCheckedContinuation { continuation in
//模拟网络请求
DispatchQueue.global().asyncAfter(deadline: .now() + 5) {
var success = Bool.random()
if success{
let str = "ret Str"
//当异步操作完成时,调用 continuation.resume(returning: data) 来恢复暂停的函数并返回结果
continuation.resume(returning: str)
}else{
continuation.resume(returning: "Error")
}
}
}
return ret1
}
/*
withCheckedThrowingContinuation
允许你抛出错误
*/
func fetchData2()async throws->String{
//<T, any Error>
let ret2 = try await withCheckedThrowingContinuation { continuation in
DispatchQueue.global().asyncAfter(deadline: .now() + 5) {
//模拟网络请求
var success = Bool.random()
if success{
let str = "ret Str"
continuation.resume(returning: str)
}else{
let error = MErr.serverError("ServerError")
continuation.resume(with: .failure(error))
}
}
}
return ret2
}
//模拟类似真实的网络请求
func fetchData3() async throws -> [String: Any] {
return try await withCheckedThrowingContinuation { continuation in
let url = URL(string: "https://example.com/user")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if let error = error {
continuation.resume(throwing: error)
return
}
guard let data = data else {
continuation.resume(throwing: NSError(domain: "com.example", code: 1, userInfo: nil))
return
}
do {
let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
if let json = json {
continuation.resume(returning: json)
} else {
continuation.resume(throwing: NSError(domain: "com.example", code: 2, userInfo: nil))
}
} catch {
continuation.resume(throwing: error)
}
}
task.resume()
}
}
/*
你在使用 withCheckedContinuation 时遇到了性能问题或需要更高级的控制,可以考虑使用 withUnsafeContinuation,但需要注意它不会进行额外的检查
withUnsafeContinuation 不会对 continuation 的使用进行检查,这意味着使用它时,你需要自己确保 continuation 的正确使用,否则可能会导致未定义的行为或程序崩溃。
*/
func fetchData4()async->String{
//<T, Never>
let ret1 = await withUnsafeContinuation { continuation in
//模拟网络请求
DispatchQueue.global().asyncAfter(deadline: .now() + 5) {
var success = Bool.random()
if success{
let str = "ret Str"
//当异步操作完成时,调用 continuation.resume(returning: data) 来恢复暂停的函数并返回结果
continuation.resume(returning: str)
}else{
continuation.resume(returning: "Error")
}
}
}
return ret1
}
/*
withThrowingTaskGroup 会自动处理子任务抛出的错误。如果任何一个子任务抛出错误,整个任务组会抛出错误,并且未完成的任务会被取消
你可以通过 group.cancelAll() 手动取消所有任务。
任务组的作用域在 withThrowingTaskGroup 闭包内。一旦闭包结束,任务组会自动等待所有任务完成
*/
func fetchData5()async throws->[Data]{
func netTaskRequest(from url:URL)async throws->Data{
let (data,_) = try await URLSession.shared.data(from: url)
return data
}
let urls = [
URL(string: "https://example.com/data1")!,
URL(string: "https://example.com/data2")!,
URL(string: "https://example.com/data3")!
]
//创建了一个任务组 group,子任务的返回类型是Data
return try await withThrowingTaskGroup(of: Data.self) { group in
var results = [Data]()
//使用 group.addTask 将每个 URL 的请求任务添加到任务组中。这些任务会并发执行
urls.forEach { url in
group.addTask {
try await netTaskRequest(from: url)
}
}
// 等待任务完成
for try await result in group{
results.append(result)
}
//返回结果
return results
}
}
/*
withThrowingDiscardingTaskGroup 是 Swift 并发编程中的一个工具,用于创建和管理一组可以抛出错误并且不需要显式收集结果的并发任务。它是 withThrowingTaskGroup 的变体,适用于你只关心任务的执行过程,而不需要收集任务返回结果的场景。
与 withThrowingTaskGroup 不同,withThrowingDiscardingTaskGroup 不会保留任务的结果,任务完成后结果会被丢弃。这使得它更适合用于执行“即发即忘”(fire-and-forget)的任务
*/
/*
withUnsafeCurrentTask 适用于以下场景:
用于在当前任务的上下文中安全地访问当前任务(Task)的引用。它允许你在一个闭包中获取当前任务的引用,并对其进行操作,例如检查任务是否被取消或获取任务的其他属性。
检查当前任务是否被取消。
获取当前任务的优先级或其他属性。
在任务上下文中执行一些与任务相关的操作。
*/
func testTask()async{
func performWork()async{
await withUnsafeCurrentTask { task in
if let task = task{
if task.isCancelled{
print("task was canceled")
return
}
print("task is running \(task.priority)")
}else{
print("current task is null")
}
}
}
/*
在这个例子中,startTask 启动了一个任务,并在 500 毫秒后取消它。performWork 函数会检查任务是否被取消,并在取消时停止工作。
*/
let task = Task{
await performWork()
}
try? await Task.sleep(nanoseconds: 50000000)
task.cancel()
}
}