// Foo2.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef void (^Reply)(id data);
typedef void (^Handler)(Reply reply);
@interface Foo2 : NSObject
- (id)initWithQueue: (dispatch_queue_t)queue;
- (void)setupHandler: (Handler)handler;
@end
NS_ASSUME_NONNULL_END
// Foo2.m
#import "Foo2.h"
@implementation Foo2 {
dispatch_queue_t _queue;
}
- (id)initWithQueue: (dispatch_queue_t)queue {
if ((self = [super init])) {
_queue = queue;
}
return self;
}
- (void)setupHandler:(Handler)handler {
dispatch_async(_queue, ^{
handler(^(id data){
NSLog(@"data is %@", data);
});
});
}
@end
然后在我的应用二进制中,我做
@preconcurrency import FooModule
let foo = Foo2(queue: .global())
foo.setupHandler { reply in
Task {
reply("foo")
}
}
在Swift 6模式下,这给了我错误(不警告):
将闭合作为“发送”参数风险,导致当前任务中的代码与封闭的并发执行
我想知道为什么@preconcurrency导入不会使错误沉默。 我尝试了另一种非关闭类型:
@interface FooNonSendable : NSObject
@property int foo;
@end
@implementation FooNonSendable
@end
在使用@preconcurrent导入之后,在我的Swift代码中:
let fooNonSendable = FooNonSendable()
Task {
Task { @MainActor in
print(fooNonSendable)
}
}
该代码没有给出任何错误或警告,这意味着@preconcurrency能够沉默foononSendable的错误,但不能闭合。
reply
只能强制构造类型以使其符合寄存以使误差保持沉默,但是您的
@preconcurrency
是一类。当您尝试通过不同的任务(Actor)调用课程时,这将像您的第一个示例一样引起数据竞赛。您的第二个示例是可以的,因为您在任务关闭中添加了@MainActor
,使您的课程仍然保持在相同的任务中(@mainactor)。要强制类型符合可发送的类型,请尝试:
extension Foo2: @unchecked Sendable {}