在 Xcode 12 中使用 @main

Ali*_*12s 7 swift swiftui ios14 xcode12

我想在 iOS 13 及更高版本上运行此代码我应该如何修复此错误?我想让这段代码也可以在 iOS 13 上运行。

@available(iOS 14.0, *)
@main

struct WeatherProApp: App {
  @Environment(\.scenePhase) private var scenePhase
  @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

  
  var body: some Scene {
    WindowGroup{
      let fetcher = WeatherFetcher()
      let viewModel = WeeklyWeatherViewModel(weatherFethcer: fetcher)
      WeeklyWeatherView(viewModel: viewModel)
    }
    .onChange(of: scenePhase) { (newScenePhase) in
      switch newScenePhase {
      case .active:
        print("scene is now active!")
      case .inactive:
        print("scene is now inactive!")
      case .background:
        print("scene is now in the background!")
      @unknown default:
        print("Apple must have added something new!")
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

但它向我展示了这个错误

错误图像

the*_*ggy 8

其实你可以使用@main属性在iOS的前14,但你需要一种替代AppDelegateSceneDelegate(你可以从iOS的13 Xcode的项目,这两个委托类复制),你必须做一些额外的包装。

首先,您必须@main通过以下方式将属性应用于具有main函数的结构,该函数根据 iOS 版本决定是使用WeatherProApp结构还是AppDelegate类来启动:

@main
struct WeatherProAppWrapper {
    static func main() {
        if #available(iOS 14.0, *) {
            WeatherProApp.main()
        }
        else {
            UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

之后,您可以使用问题中显示的实现,只需删除@main属性,只使用@available(iOS 14.0, *). 例如:

@available(iOS 14.0, *)
struct WeatherProApp: App {
    var body: some Scene {
        WindowGroup{
            ContentView()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我不确定您对 UIKit 有多熟悉,但您也必须在 SceneDelegate 类中的 WindowGroup 中进行相同的设置。


Ugo*_*lli 8

按照@the.blaggy 的回答,以下是我如何在 iOS 13 上运行我的项目:

  1. 如果没有,请创建一个 SceneDelegate

SceneDelegate.swift

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        let contentView = ContentView()

        // Use a UIHostingController as window root view controller.
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: contentView)
            self.window = window
            window.makeKeyAndVisible()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 打开您的 info.plist 作为源代码并添加这些行:

信息表

   <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>
Run Code Online (Sandbox Code Playgroud)
  1. 将此添加到您的 WeatherProApp.swift

WeatherProApp.swift

    @main
    struct WeatherProAppWrapper {
        static func main() {
            if #available(iOS 14.0, *) {
                WeatherProApp.main()
            }
            else {
                UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(SceneDelegate.self))
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的评论,它真的很有帮助。只需添加一条小评论,因为有些人可能会像我一样遇到困难,如果您因为从 Xcode 13 创建应用程序而找不到“info.plist”,您可以打开目标然后选择信息,然后添加任何键,然后info.plist 将出现在项目导航器中,您可以在那里编辑它。 (3认同)

Asp*_*eri 3

这可能取决于其他项目代码,但以下测试有效(Xcode 12b),因此可能会有所帮助。

这个想法是通过可用性检查器将一个包装器隐藏在另一个结构中:

@available(iOS 14.0, macOS 10.16, *)
struct Testing_SwiftUI2AppHolder {
    @main
    struct Testing_SwiftUI2App: App {

        var body: some Scene {
            WindowGroup {
                ContentView()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)