Xcode 11 Beta 5调用@Published变量的sink时触发Abort trap:6错误
关于Swift包中@Published变量订阅sink触发编译错误的问题
我之前也遇到过完全一样的情况,目前来看这大概率是Swift Combine Beta版本里的一个已知bug,尤其是在跨模块(独立Swift包)场景下使用@Published属性时特别容易触发。
先对齐你的场景特征:
- 独立Swift包中的仓库类定义了
@Published public var state: UserState = .initial - 在测试或主应用中通过
$state订阅sink时,抛出包含Global is external, but doesn't have external or weak linkage!的编译错误,直接导致Abort trap: 6 - 使用Just、Future等其他Combine Publisher时完全正常,没有任何编译问题
- 从Beta4开始出现该问题,Beta5更新后仍未修复
可以尝试的临时变通方案:
虽然这是Apple端的问题,但我们可以通过一些写法绕过这个bug:
手动封装Publisher替代@Published
放弃直接使用@Published,改用CurrentValueSubject手动实现状态发布逻辑,对外暴露统一的Publisher接口,比如:public class Authentication { public static let shared = Authentication() private let _state = CurrentValueSubject<UserState, Never>(.initial) // 对外的状态属性 public var state: UserState { get { _state.value } set { _state.send(newValue) } } // 对外暴露的订阅接口 public var statePublisher: AnyPublisher<UserState, Never> { _state.eraseToAnyPublisher() } func login(with credentials: Credentials) { // 登录逻辑执行后,通过_state.send更新状态 _state.send(.loggedIn) } }测试时直接订阅
statePublisher即可,完全可以达到和@Published一样的效果,同时避开编译bug。调整模块访问控制(限同模块测试)
如果你的测试代码和仓库类在同一个模块内,可以尝试把Authentication类的访问级别从public改为internal,有时候跨模块的访问控制会和Combine的内部实现冲突。清理构建缓存
有时候Xcode的旧缓存会放大这类编译bug,尝试执行Cmd+Shift+K清理构建文件夹,或者手动删除DerivedData目录后重新编译,说不定能临时解决问题。
关于跨模块使用@Published的成功案例:
目前在Beta版本的生态里,很多开发者都踩过这个坑,暂时还没看到有人能直接在跨模块场景下使用@Published的sink而不触发错误。你的判断完全正确,这确实是Apple Combine的Beta版本bug,建议你通过Feedback Assistant提交bug报告,附上你的测试项目和崩溃日志,帮助官方更快定位修复。
内容的提问来源于stack exchange,提问作者gujci
相关产品推荐
相关产品推荐

