NS_SWIFT_UI_ACTOR 注释不适用于基于回调的 Objective-C 方法的异步变体
在Objective-C中,我们可以使用NS_SWIFT_UI_ACTOR
指示应在主演员上执行方法或整个类(就像我们在Swift中使用@mainactor
一样)。这是正确起作用的,因为当调用一种从主演员外部返回值的方法(使用Task.tected.tected.thecked.staberct Priarity)时,编译器迫使我们使用“等待”来调用它(允许“ Actor Switch”)和,在运行时,我可以看到该代码是在主线程上执行的。
但是,当在同一类调用基于回调的方法时(该方法会自动获得“导入”异步变体,如说明在这里)NS_SWIFT_UI_ACTOR似乎无法正常工作,并且代码在后台线程上执行。
NS_SWIFT_UI_ACTOR
@interface ObjcClass : NSObject
- (NSString *)method1;
- (void)method2WithCompletion: (void (^)(NSString * _Nonnull))completion;
@end
Task.detached(priority: .background) {
let objcInstance = ObjcClass()
print(await objcInstance.method1()) <----- this is called on the main thread
print(await objcInstance.method2()) <----- this is called on a bg thread
}
In Objective-c we can use NS_SWIFT_UI_ACTOR
to indicate that a method or a whole class should be executed on the main actor (as we would do with @MainActor
in Swift). This works correctly since, when invoking a method which returns a value from outside the main actor (using a Task.detached with background priority), the compiler forces us to call it using "await" (to allow for "actor switch") and, at runtime, I can see that the code is executed on the main thread.
However, when calling a callback based method on the same class (which gets an automatically "imported" async variant, as explained here) the NS_SWIFT_UI_ACTOR seems not working properly, and the code is executed on a background thread.
NS_SWIFT_UI_ACTOR
@interface ObjcClass : NSObject
- (NSString *)method1;
- (void)method2WithCompletion: (void (^)(NSString * _Nonnull))completion;
@end
Task.detached(priority: .background) {
let objcInstance = ObjcClass()
print(await objcInstance.method1()) <----- this is called on the main thread
print(await objcInstance.method2()) <----- this is called on a bg thread
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
虽然我了解您的期望是什么,但我现在不认为演员的实施方式可以解决此问题。 Swift中的参与者是重新进入的,这意味着每当您调用Actor的方法/Actor任务中的任何
async
方法时,Actor都会暂停当前任务,直到方法返回并开始处理其他任务为止。这种重新进入行为很重要,因为它不仅在执行长期任务时锁定演员。让我们以
mainactor
隔离async
方法的示例:但是由于Swift无法从目标C
async
方法中推断出哪一部分应在MainActor
以及哪个部分演员只能暂停当前任务以处理其他任务,整个async
方法不隔离到演员。但是,当前有一些建议允许定制演员的重新输入,以便您可以在Actor上执行整个OBJC
async
方法。While I understand what your expectation is I don't think as of now the way actor is implemented there is any way to resolve this. Actors in swift are reentrant, which means whenever you invoke any
async
method inside actor's method/actor task, actor suspends the current task until the method returns and starts processing other tasks. This reentrancy behavior is important as it doesn't just lock the actor when executing a long-running task.Let's take an example of a
MainActor
isolatedasync
method:But since swift can't infer from an objective c
async
method which part should run onMainActor
and for which part actor can just suspend the current task to process other tasks, the entireasync
method isn't isolated to the actor.However, there are proposals currently to allow customizing an actor's reentrancy so you might be able to execute the entire objc
async
method on the actor.