Swift项目中如何重写自定义框架类/结构体的部分常量?
解决框架常量部分重写的方案
你的问题核心是Swift不允许同一命名空间下存在同名结构体,直接在子项目里重新定义AppSettings会导致编译冲突。下面提供两种实用方案,实现只重写框架中需要修改的常量:
方案一:协议+默认实现(推荐,符合Swift值类型设计)
把框架中的AppSettings改成协议,通过扩展提供默认值,子项目只需实现协议并覆盖需要修改的常量即可。
框架侧代码
// 定义协议,声明所有需要的常量 public protocol AppSettingsProtocol { static var columnCountLandscape: Int { get } static var columnCountPortrait: Int { get } static var appName: String { get } static var imageZoomFactor: CGFloat { get } static var version: String { get } static var applicationType: String { get } } // 扩展协议,提供默认实现 public extension AppSettingsProtocol { static var columnCountLandscape: Int { 0 } static var columnCountPortrait: Int { 0 } static var appName: String { "base" } static var imageZoomFactor: CGFloat { 1.0 } static var version: String { Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "" } static var applicationType: String { "" } } // 框架内部定义默认实现的结构体 public struct DefaultAppSettings: AppSettingsProtocol {} @main struct MyFramework: App { // 全局变量用于子项目注入自定义配置 public static var currentSettings: AppSettingsProtocol.Type = DefaultAppSettings.self var body: some Scene { WindowGroup { switch Self.currentSettings.applicationType { case "A": AView() case "B": BView() case "C": CView() default: EmptyView() } } } }
子项目侧代码
// 实现协议,只重写需要修改的常量 struct CustomAppSettings: AppSettingsProtocol { static let appName: String = "MyApp" static let columnCountLandscape: Int = 3 static let applicationType: String = "B" // 其他未重写的常量自动使用协议扩展的默认值 } @main struct MyApp: App { init() { // 注入自定义配置 MyFramework.currentSettings = CustomAppSettings.self } var body: some Scene { MyFramework().body } }
方案二:使用类的继承(适合面向对象场景)
由于结构体不支持继承,把框架中的AppSettings改成open类,子项目继承后重写需要的静态属性。
框架侧代码
open class AppSettings { open class var columnCountLandscape: Int { 0 } open class var columnCountPortrait: Int { 0 } open class var appName: String { "base" } open class var imageZoomFactor: CGFloat { 1.0 } open class var version: String { Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "" } open class var applicationType: String { "" } } @main struct MyFramework: App { // 全局变量用于子项目替换配置类 public static var currentSettings: AppSettings.Type = AppSettings.self var body: some Scene { WindowGroup { switch Self.currentSettings.applicationType { case "A": AView() case "B": BView() case "C": CView() default: EmptyView() } } } }
子项目侧代码
class CustomAppSettings: AppSettings { override class var appName: String { "MyApp" } override class var columnCountLandscape: Int { 3 } override class var applicationType: String { "B" } } @main struct MyApp: App { init() { // 替换为自定义配置类 MyFramework.currentSettings = CustomAppSettings.self } var body: some Scene { MyFramework().body } }
额外说明
- 两种方案都避免了类型冲突,同时保留未修改常量的默认值
- 如果子项目不需要自定义
@main入口,也可以在框架初始化阶段注入自定义配置 - 优先推荐方案一,符合Swift值类型设计理念,扩展性更强
内容的提问来源于stack exchange,提问作者nirav dinmali
相关产品推荐
相关产品推荐

