资讯动态

Swift 应用入口点演进:SE-0383 弃用 @UIApplicationMain 与 @NSApplicationMain,全面迁移到 @main

发布时间:2026/9/23 3:34:41 来源:尧图企业网站定制
文档【免费下载链接】swift-evolutionThis maintains proposals for changes and user-visible enhancements to the Swift Programming Language.项目地址https://gitcode.com/gh_mirrors/sw/swift-evolution点击查看免费下载导读本文基于 swift-evolution 仓库中的 SE-0383 提案已实现随 Swift 5.10 落地系统讲解 Swift 如何终结UIApplicationMain与NSApplicationMain这两个框架专属入口点属性并将其收编到统一的main属性之下。你将掌握为什么会出现两个功能等价的入口点写法、编译器在 Swift 5 与 Swift 6 语言模式下分别如何处置旧属性、如何通过一行 fix-it 完成迁移、以及如何通过-enable-upcoming-feature DeprecateApplicationMain与 SwiftPM 的SwiftSetting提前启用该行为为 Swift 6 迁移做准备。背景两条入口点路线的由来在 Swift 语言中程序的执行入口点有两种表达方式框架专属属性iOS/macOS 应用长期使用UIApplicationMainUIKit与NSApplicationMainAppKit声明一个由编译器合成的、平台特定的应用入口点通用属性由 SE-0281mainType-Based Program Entry Points已实现随 Swift 5.3 落地引入的main属性用类型标注的方式统一指定程序入口。SE-0281 的核心机制是被main标注的类型只需提供一个静态main()方法该方法通常由框架或库通过协议扩展提供编译器在程序启动时调用该类型上的静态main()。SE-0281 在描述动机时已经预告了这一天UIKit 与 AppKit 可以给UIApplicationDelegate、NSApplicationDelegate协议补充静态main()的默认实现从而让作者只用统一的main属性并允许弃用这些专用属性0281-main-attribute.md。SE-0383 正是完成这一收尾工作的提案。动机两个功能等价、最终冗余的入口点UIKit 与 AppKit 已经全面拥抱main只要应用类型遵循UIApplicationDelegate或NSApplicationDelegate协议即可无缝采用该属性。SE-0383 指出这给应用作者呈现了两个本质上多余的选择使用写死的框架专属属性UIApplicationMain或NSApplicationMain使用更通用的main属性。在运行时对于遵循上述应用委托协议之一的类main的行为与对应的框架专属属性完全一致。SE-0383 的评价是用两种功能完全相同的写法来表达应用入口点这一概念轻则算是语言中的冗余clutter重则造成困惑confusing。提案的意图是通过编译器推动 Swift 作者走向更通用、统一的解决方案即完成 SE-0281 暗含的迁移工作。方案总览警告先行Swift 6 变为硬错误SE-0383 的行为分语言模式两级递进语言模式使用UIApplicationMain/NSApplicationMain的结果Swift 5 及更早pre-Swift 6无条件警告并提供 fix-it 建议替换为相应的协议遵循即mainSwift 6 及以后硬错误hard error这意味着该特性同时是一个 SE-0362 分阶段未来特性 意义上的Upcoming Feature Flag其标识符为DeprecateApplicationMain见 0383-deprecate-uiapplicationmain-and-nsapplicationmain.md允许开发者在 Swift 5 时代提前体验 Swift 6 的弃用语义。详细设计编译器如何诊断与迁移由于UIApplicationMain与NSApplicationMain的用法完全相同提案的详细设计部分只讨论UIApplicationMainNSApplicationMain遵循完全相同的模式。框架专属属性的工作机制这些框架专属属性被加入语言是为了自动化声明标准应用入口点所需的样板代码。在 UIKit 代码中入口点最终总是以调用UIApplicationMain结尾而该调用的最后一个参数是某个UIApplicationDelegate子类的名字——UIKit 会查找并实例化这个委托类以便向其发出应用生命周期回调。因此Swift 要求该属性出现在一个遵循UIApplicationDelegate协议的类上以便把该类名提供给 UIKit。关键点在于对UIApplicationDelegate的遵循带来的不止生命周期回调符合要求的类型还免费获得一个main入口点的默认实现而UIApplicationMain属性恰恰会抑制suppress它。正是这一点构成了既有用户迁移路径的核心——移除旧属性后编译器会自动回落到由协议遵循继承而来的main入口点。诊断与 fix-it按本提案当编译器看到UIApplicationMain的使用时会发出包含替换建议的诊断信息在 Swift 6 及以后的语言模式下是错误否则是警告。警告文本与 fix-it 如下UIApplicationMain // warning: UIApplicationMain is deprecated in Swift 5 // fixit: Change UIApplicationMain to main final class MyApplication: UIResponder, UIApplicationDelegate { /**/ }应用 fix-it 之后的结果main final class MyApplication: UIResponder, UIApplicationDelegate { /**/ }迁移后的行为这一步简单的迁移会让编译器选择由UIApplicationDelegate遵循所继承的main入口点不需要任何额外的源码改动。NSApplicationMain的迁移完全相同只是将类改为遵循NSApplicationDelegate。如何在 Swift 6 之前提前启用弃用行为编译器命令行方式DeprecateApplicationMain是 SE-0362 定义的 upcoming feature。按 0362-piecemeal-future-features.md可通过编译器 flag 逐个启用swiftc -enable-upcoming-feature DeprecateApplicationMain main.swift该 flag 的特点依据 SE-0362 的通用机制多个 upcoming feature 可以重复传多个-enable-upcoming-feature同时启用每个 upcoming feature 都在某个语言版本中默认开启当语言版本已经默认开启该特性时再显式传入 flag 会产生错误提醒开发者清理配置效果不会跨模块边界传播——依赖此模块的其他 target 无需传递该 flag。SwiftPM 清单方式在 Package.swift 中可通过SwiftSetting.enableUpcomingFeature(_:_:)为 target 指定所需的 upcoming featureAPI 签名见 0362-piecemeal-future-features.mdextension SwiftSetting { public static func enableUpcomingFeature( _ name: String, _ condition: BuildSettingCondition? nil ) - SwiftSetting }典型用法// swift-tools-version:5.9 import PackageDescription let package Package( name: MyApp, targets: [ .executableTarget( name: MyApp, swiftSettings: [ .enableUpcomingFeature(DeprecateApplicationMain) ] ) ] )SwiftPM 会在构建该模块时把列表中每个 upcoming feature 通过-enable-upcoming-feature传给编译器。特性名以字符串形式提供因此 SwiftPM 的清单格式无需随编译器新增特性而改变依赖该 target 的其他 target 不需要传递这些 flag。与迁移工具化的关系机械化迁移SE-0383 属于有机械化迁移路径mechanical migration的特性即编译器能够精确确定让代码在新语义下继续编译所需的源码修改且保持行为不变。在 SE-0486 迁移工具化已实现随 Swift 6.2 落地的自动化迁移清单中DeprecateApplicationMain被明确列为可完全自动应用的调整之一UIApplicationMain→main、NSApplicationMain→main0486-adoption-tooling-for-swift-features.md。这意味着除了手工应用编辑器中的 fix-it还可以借助迁移模式批量完成整个项目的入口点改造进一步降低升级成本。源码兼容性影响Swift 5 及更早模式现有 Swift 库继续可编译因为它们在 pre-Swift 6 语言模式下编译该模式仅新增一个使用框架专属入口点时的无条件警告并提供诊断以避免警告、自动迁移用户代码。Swift 6 及以后模式本提案有意造成源码不兼容——编译器遇到框架专属属性会发出无条件错误。这一破坏主要落在较老的应用代码上因为大多数库与包并不用框架专属属性定义 main 入口点较新的代码包括 Xcode 14 及以后提供的应用模板已经使用main属性。对 ABI 稳定性的影响本提案对 ABI 无影响它只是改变编译器对既有属性的诊断级别与推荐写法不改变任何已编译代码的符号、调用约定或运行时行为也不涉及标准库或运行时交互。对 API 弹性API resilience同样没有任何影响。实践建议迁移检查清单结合 SE-0383 与上文机制向main迁移的推荐路径如下确认目标最低版本main需要 Swift 5.3SE-0281 的落地版本DeprecateApplicationMain的警告需要 Swift 5.10Swift 6 语言模式才会报错全局搜索旧属性在工程中搜索UIApplicationMain与NSApplicationMain逐一应用 fix-it 或由迁移工具批量替换为main验证类遵循协议替换后确保类仍遵循UIApplicationDelegate或NSApplicationDelegatemain入口点由协议默认实现提供提前启用特性在 Package.swift 的swiftSettings中加入.enableUpcomingFeature(DeprecateApplicationMain)或构建时传入-enable-upcoming-feature DeprecateApplicationMain在 Swift 5 模式下提前暴露并修复所有旧属性使用点最后切换到 Swift 6 语言模式此时旧属性已是硬错误若此前步骤彻底迁移应无残留报错。总结SE-0383 以警告先行、Swift 6 硬错误的两级策略把UIApplicationMain与NSApplicationMain正式送入历史使main成为 Swift 中表达应用入口点的唯一标准写法。对开发者而言迁移成本极低——一条 fix-it 即可完成且运行时行为完全不变对语言而言则消除了入口点表述上的重复与困惑。仓库中 SE-0281、SE-0362、SE-0486 与 SE-0383 四份提案共同构成了从统一入口点、分阶段启用、到机械化迁移的完整演进链条值得在升级 Swift 6 时一并研读。赞分享文档【免费下载链接】swift-evolutionThis maintains proposals for changes and user-visible enhancements to the Swift Programming Language.项目地址https://gitcode.com/gh_mirrors/sw/swift-evolution点击查看免费下载相关推荐BuildKit 弃用功能演进与迁移指南从 Build information 到 SLSA Provenance AttestationsBuildKit 弃用功能演进与迁移指南从 Build information 到 SLSA Provenance Attestations BuildKit构建工具云原生后端FirebaseMLModelDownloader 版本演进与维护指南从遥测清理到弃用迁移FirebaseMLModelDownloader 版本演进与维护指南从遥测清理到弃用迁移 FirebaseMLModelDownloader 是 Fireb移动开发后端认证鉴权Swift 的 main 属性基于类型声明程序入口点的完整指南SE-0281Swift 的 main 属性基于类型声明程序入口点的完整指南SE 0281 本文基于 Swift Evolution 提案 SE 0281《main文档创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价