SwiftUI Widget扩展如何访问UIKit主项目的结构体、枚举等代码资源
问题根因
Widget 扩展属于独立的 Extension Target,和主 App Target 运行在完全隔离的沙箱与进程中,二者默认处于编译隔离状态,你无法直接通过导入主 App 模块的方式访问主 Target 内的代码,之前导入 MyApp 模块后依然无法访问的问题就是由该架构隔离规则导致的。
解决方案(按推荐优先级排序)
方案1:抽取公共代码到共享框架(官方推荐,长期维护成本最低)
这是苹果官方建议的跨 Target 代码复用方案,操作步骤如下:
- 在 Xcode 中新建一个 Framework 类型的 Target,可命名为类似
MyAppCore - 将需要在主 App 和 Widget 中同时使用的模型结构体、枚举、工具类,从主 Target 的成员资格中移除,改为勾选
MyAppCore的 Target 成员资格 - 所有抽入
MyAppCore的类型、方法、属性,都需要加上public(按需选择open)访问控制修饰符,同时要手动添加公开的初始化方法,示例如下:
// 原主项目中声明的模型 struct UserModel { let name: String let avatar: String } // 抽入 MyAppCore 后的声明 public struct UserModel { public let name: String public let avatar: String public init(name: String, avatar: String) { self.name = name self.avatar = avatar } }
- 分别进入主 App Target 和 Widget Extension Target 的
General-Frameworks, Libraries, and Embedded Content配置项,添加MyAppCore依赖 - 后续在主 App 和 Widget 的代码中,只要导入
import MyAppCore即可访问所有共享的公共代码
方案2:直接勾选 Target 成员资格(适合小型项目快速验证)
如果项目规模较小,不想额外维护独立框架,可以使用更轻量的实现方式:
- 选中需要给 Widget 复用的文件,打开 Xcode 右侧的检查器面板,找到
Target Membership配置项 - 除原有主 App Target 外,额外勾选你的 Widget Extension Target 即可
- 该方式不需要导入任何额外模块,直接即可在 Widget 中访问对应类型,缺点是后续新增其他扩展(如 Watch 扩展、灵动岛扩展等)时需要重复勾选,代码复用管理成本会随项目迭代上升。
注意事项
- 共享代码中不能包含主 App 独有的、扩展禁用的 API(比如
UIApplication.shared),否则会触发编译报错 - 如果需要在主 App 和 Widget 之间同步运行时数据,不能使用默认的
UserDefaults.standard,需要通过配置 App Group 实现共享存储。
内容的提问来源于stack exchange,提问作者Marmaduk
相关产品推荐
相关产品推荐

