【发布时间】:2025-12-29 14:10:12
【问题描述】:
我在 Xcode 12 中创建了一个项目,其中 iOS 14 作为部署目标(更大的项目)。一段时间后,我意识到我还必须能够支持 iOS 13 设备。我的项目使用 SwiftUI。
将部署目标简单地更改为 iOS 13 显然不是很直接,因为 Xcode 12 生成的某些代码不向后兼容 iOS 13。
所以我基本上需要将我的基于 Xcode 12 的项目(当前部署目标为 iOS 14.0)转换为也支持 iOS 13。
这是我为项目降级所做的准备工作:
- 安装 Xcode 11.7,创建支持 SwiftUI 的新项目,并确保部署目标是 iOS 13.0。因此,我知道 Xcode 认为“iOS 13”方式应该是什么,即使用 AppDelegate 和 SceneDelegate。
- 运行该应用 - 在我的 iOS 14 设备上运行良好。
- 打开 Xcode 12,创建支持 SwiftUI 的新项目,将部署目标降低到 iOS 13.0(因为它默认设置为 14.x),构建它,然后出现一堆编译问题(如预期的那样)。
随后对 Xcode 12 项目进行了更改:
- 注释掉
<project>App.swift文件中的所有内容。 - 添加与上述 Xcode 11.7 生成的项目中内容相同的 AppDelegate.swift 文件。
- 添加与上述 Xcode 11.7 生成项目中内容相同的 SceneDelegate.swift 文件。
- 添加 LaunchScreen.storyboard 文件(因为 Xcode 警告它不存在)。
- 运行应用程序。
应用程序运行,但ContentView 的内容未显示。只是一个黑屏(黑色可能是因为我的设备处于黑暗模式)。此外,正如您将在下面的代码中注意到的那样,我插入了调试日志,但控制台中只打印了“didFinishLaunchingWithOptions”——也就是说,似乎没有调用场景委托方法。
我(当然)用 Google 搜索了很多,用 Info.plist 尝试了各种方法,但似乎没有任何帮助。
代码:
AppDelegate.swift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
print("didFinishLaunchingWithOptions")
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
print("configurationForConnecting")
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
print("didDiscardSceneSessions")
}
}
SceneDelegate.swift
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
print("scene willConnectTo")
guard let windowScene = scene as? UIWindowScene else { return }
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: ContentView())
self.window = window
window.makeKeyAndVisible()
}
func sceneDidDisconnect(_ scene: UIScene) {
print("sceneDidDisconnect")
}
func sceneDidBecomeActive(_ scene: UIScene) {
print("sceneDidBecomeActive")
}
func sceneWillResignActive(_ scene: UIScene) {
print("sceneWillResignActive")
}
func sceneWillEnterForeground(_ scene: UIScene) {
print("sceneWillEnterForeground")
}
func sceneDidEnterBackground(_ scene: UIScene) {
print("sceneDidEnterBackground")
}
}
ContentView.swift
struct ContentView: View {
var body: some View {
Text("Hello, world!")
.foregroundColor(.blue)
.padding()
.onAppear {
print("ContentView")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string></string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchScreen</key>
<dict/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
【问题讨论】:
-
我看不出这有什么意义。在 Xcode 12 中创建 SwiftUI 项目时,您可以选择使用向后兼容的应用程序委托生命周期。所以就这样做吧。
-
@matt 是的,如果我要开始一个新项目,那会起作用。我的观点是我有一个现有的 Xcode 12 项目,它是使用“SwiftUI 方式”创建的,因此我需要一种方法来配置现有项目以使用“非 SwiftUI 方式”。我只是尝试根据您的建议创建一个新项目,并试图从中找出不同之处。唯一的问题是它使用
@main而不是@UIApplicationMain,但就我所见,仅此而已。
标签: ios swiftui ios13 ios14 xcode12