如何让参与者遵守协议Sequence?以下代码生成编译器警告:
与全局参与者“MainActor”隔离的实例方法“makeIterator()”无法满足协议“Sequence”的相应要求
@MainActor class Test: Sequence {
private var contents: [Int] = []
func makeIterator() -> Array<Int>.Iterator {
contents.makeIterator()
}
}
Run Code Online (Sandbox Code Playgroud) 我想创建一个异步函数,它本身使用异步调用。我还想确保在任何时刻只有一个呼叫被主动处理。所以我想要一个async @synchronized函数。
怎么做?将函数体包装在 内并dispatchQueue.sync {}不能像它期望的同步代码那样工作。另外,似乎DispatchQueue一般不设计有要执行的异步代码块/任务。
该代码与硬件通信,因此本质上是异步的,这就是为什么我想要为我的库提供异步接口。(我不想在通信阶段发生时阻止应用程序。)但是某些操作无法在硬件上并行执行,因此我必须进行同步,以便某些操作不会同时发生。
class ViewModel: ObservableObject { }
struct ContentView: View {
@StateObject private var model = ViewModel()
var body: some View {
Button("Authenticate", action: doWork)
}
func doWork() {
Task.detached {
for i in 1...10_000 {
print("In Task 1: \(i)")
}
}
Task.detached {
for i in 1...10_000 {
print("In Task 2: \(i)")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是https://www.hackingwithswift.com/quick-start/concurrency/whats-the-difference- Between-a-task-and-a-detached-task 中描述的代码。
由于 doWork 中的任务是分离的,我希望它们同时执行。上面的文章也是这么说的。
但是,当我运行它时,Task2 在 Task1 之后执行。
我错了吗?
我使用 firebase 的实时数据库从我的应用程序进行异步数据库查询。现在 iOS 15 为我们提供了 Swift 5.5,我喜欢使用async/await来执行这些查询,而不是传递完成闭包。
我知道我可以使用await withCheckedThrowingContinuation { }现有的 firebase 函数构建异步版本。但是异步版本已经存在吗?在 firebase 中还是由 Xcode 自动合成?
async-await firebase swift firebase-realtime-database swift-concurrency
是否可以在 UIKit 中使用 async/await 进行 POST HTTP 请求,即 from UIButton?
我可以发送请求,但它立即崩溃。完美地使用URLSession,并以此作为学习经验。
lazy var buttonTest: UIButton = {
let button = UIButton()
button.addTarget(self, action: #selector(testAsyncTwo), for: .touchUpInside)
return button
}()
@objc func testAsync() async throws {
let date = Date()
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd HH:mm:ss"
let dateString = df.string(from: date)
let json: [String: Any] = ["item": "1",
"time": "\(dateString)"]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
guard let url = URL(string: "https://myapiendpoint.com/api/") else { fatalError("Missing URL") …Run Code Online (Sandbox Code Playgroud) 这段代码似乎总是像魔术一样工作。没有任何锁定,输出为 1,2。
class Counter {
var count = 0
func increment() -> Int {
count += 1
return count
}
}
class ViewController: UIViewController {
var tasks = [Task<Void, Never>]()
override func viewDidLoad() {
super.viewDidLoad()
let counter = Counter()
tasks += [
Task.detached {
print(counter.increment())
}
]
tasks += [
Task.detached {
print(counter.increment())
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
此代码来自https://www.andyibanez.com/posts/understanding-actors-in-the-new-concurrency-model-in-swift/
我预计它会不一致地工作。我尝试将其切换为不使用分离任务,但它仍然总是返回 1,2。到底是怎么回事?
对于这个 swift 游乐场(查看 swiftfiddle或以下),我有三个流程密集型工作循环。使用线程的线程会产生 50 个线程,所有线程一起工作(通过最后报告的循环数量的增加来显示),而具有并发性的线程只会同时执行两个任务。什么决定了要在其中运行任务的线程数?正如我在评论中提到的,一种方法不一定比另一种方法更快,因为 50 个线程竞争资源远非理想,但 2 似乎是一个非常低的数字。
import PlaygroundSupport
import UIKit
PlaygroundPage.current.needsIndefiniteExecution = true
func asyncProcess(_ this:Int) async{
print(" async -- starting \(this)")
let x = Int.random(in: 1000...10000000)
await withUnsafeContinuation{
for _ in 1..<x {}
$0.resume()
}
print(" async -- ending \(this) after \(x) times")
}
func threadedProcess(_ this:Int) {
print("threaded -- starting \(this) on \(Thread.current)")
let x = Int.random(in: 1000...10000000)
for _ in 1..<x {}
print("threaded -- ending \(this) after \(x) times on \(Thread.current)") …Run Code Online (Sandbox Code Playgroud) 根据保留抛出表达式的结果文档,可以将抛出表达式转换为Result类型,如下所示:
let singleSample = Result { try UnreliableRandomGenerator().random() }
Run Code Online (Sandbox Code Playgroud)
是否也可以将async抛出表达式转换为Result如下类型:
let singleSample = Result { try await UnreliableRandomGenerator().random() }
Run Code Online (Sandbox Code Playgroud) 我有一个视图模型声明如下:
@MainActor class ContentViewModel: ObservableObject {
...
}
Run Code Online (Sandbox Code Playgroud)
我想向该模型添加一个函数,该函数在MainActor上下文内部和外部混合执行工作。
我进行了一些实验,并提出了两个实现此目的的选项,如下所述。
在视图模型中将新函数标记为nonisolated并在该函数内启动一个任务,如下所示:
nonisolated func someFunction() {
Task {
// Do work here.
// Use 'await' to make calls to the 'MainActor' context
// and to make other asynchronous calls.
}
}
Run Code Online (Sandbox Code Playgroud)
在视图中调用该函数如下:
Button("Execute") {
viewModel.someFunction()
}
Run Code Online (Sandbox Code Playgroud)
在视图模型中将新函数标记为async并省略任务启动,如下所示:
func someFunction() async {
// Do work here.
// No need to 'await' to make calls to the 'MainActor' context
// given …Run Code Online (Sandbox Code Playgroud) 我正在观看有关使用 Swift Actor 保护可变状态的WWDC 视频
在一个示例中,他们展示了如何同时调用参与者方法
想象一下,我们有两个不同的并发任务试图同时获取相同的图像。第一个发现没有缓存条目,开始从服务器下载图像,然后被挂起,因为下载需要一段时间。当第一个任务是下载映像时,新映像可能会部署到同一 URL 下的服务器。现在,第二个并发任务尝试获取该 URL 下的图像。它还看不到缓存条目,因为第一次下载尚未完成,然后开始图像的第二次下载。下载完成时它也会被暂停。一段时间后,其中一个下载(假设这是第一个下载)将完成,并且其任务将在 Actor 上恢复执行。它填充缓存并返回猫的结果图像。现在第二个任务已完成下载,因此它被唤醒。它用它得到的悲伤猫的图像覆盖缓存中的相同条目。因此,即使缓存中已经填充了图像,我们现在也会为同一 URL 获取不同的图像。
Actor 的整个想法不就是确保在任何给定时间只有一个调用者可以直接与 Actor 交互吗?
这是我的例子。在这里您可以看到“BEGIN增量”后面始终跟着“END增量”,并且后续调用increment必须等待
actor Counter {
var count = 1
func increment() {
print("BEGIN increment")
let url = URL(string: "https://google.com")!
let data = try! Data(contentsOf: url)
let string = String(data: data, encoding: .utf8) ?? ""
print("END increment")
count += 1
}
}
struct ContentView: View {
@State var counter = Counter()
var body: some View {
Button {
Task.detached { …Run Code Online (Sandbox Code Playgroud)