在 Xcode 12 中使用@main
use @main in Xcode 12
我想 运行 在 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!")
}
}
}
}
但它向我显示了这个错误
这可能取决于其他项目代码,但以下测试有效 (Xcode 12b),因此可能会有所帮助。
想法是使用可用性检查器将一个包装器隐藏在另一个结构中:
@available(iOS 14.0, macOS 10.16, *)
struct Testing_SwiftUI2AppHolder {
@main
struct Testing_SwiftUI2App: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
}
实际上你可以在 iOS 14 之前使用 @main
属性但是你需要一个替代的 AppDelegate
和 SceneDelegate
(你可以复制这两个委托 classes 来自 iOS 13 Xcode 个项目)并且你必须做一些额外的包装。
首先,您必须按以下方式将 @main
属性应用于具有 main
函数的结构,该函数根据 iOS 版本决定是否使用 WeatherProApp
结构或 AppDelegate
class 启动:
@main
struct WeatherProAppWrapper {
static func main() {
if #available(iOS 14.0, *) {
WeatherProApp.main()
}
else {
UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self))
}
}
}
之后您可以使用问题中显示的实现,只需删除 @main
属性,仅使用 @available(iOS 14.0, *)
。例如:
@available(iOS 14.0, *)
struct WeatherProApp: App {
var body: some Scene {
WindowGroup{
ContentView()
}
}
}
我不确定您对 UIKit 的熟悉程度,但您也必须在 SceneDelegate class 的 WindowGroup 中进行相同的设置。
根据 @the.blaggy 的回答,以下是我如何在 iOS 13 上 运行 我的项目:
- 如果没有 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()
}
}
}
- 打开您的 info.plist 作为源代码并添加这些行:
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>
- 将此添加到您的 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))
}
}
}
如果你真的需要它,只需将@main 更改为@UIApplicationMain,它应该可以解决问题。
结合@the.blaggy 和@Ugo Marinelli 的回答,我通过修改我的 AppDelegate 使其工作,而无需创建新的 SceneDelegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(
_: UIApplication,
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = UIHostingController(
rootView: ContentView()
)
self.window = window
window.makeKeyAndVisible()
return true
}
}
我也像@the.blaggy 那样包装了我的主要结构。
我想 运行 在 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!")
}
}
}
}
但它向我显示了这个错误
这可能取决于其他项目代码,但以下测试有效 (Xcode 12b),因此可能会有所帮助。
想法是使用可用性检查器将一个包装器隐藏在另一个结构中:
@available(iOS 14.0, macOS 10.16, *)
struct Testing_SwiftUI2AppHolder {
@main
struct Testing_SwiftUI2App: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
}
实际上你可以在 iOS 14 之前使用 @main
属性但是你需要一个替代的 AppDelegate
和 SceneDelegate
(你可以复制这两个委托 classes 来自 iOS 13 Xcode 个项目)并且你必须做一些额外的包装。
首先,您必须按以下方式将 @main
属性应用于具有 main
函数的结构,该函数根据 iOS 版本决定是否使用 WeatherProApp
结构或 AppDelegate
class 启动:
@main
struct WeatherProAppWrapper {
static func main() {
if #available(iOS 14.0, *) {
WeatherProApp.main()
}
else {
UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self))
}
}
}
之后您可以使用问题中显示的实现,只需删除 @main
属性,仅使用 @available(iOS 14.0, *)
。例如:
@available(iOS 14.0, *)
struct WeatherProApp: App {
var body: some Scene {
WindowGroup{
ContentView()
}
}
}
我不确定您对 UIKit 的熟悉程度,但您也必须在 SceneDelegate class 的 WindowGroup 中进行相同的设置。
根据 @the.blaggy 的回答,以下是我如何在 iOS 13 上 运行 我的项目:
- 如果没有 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()
}
}
}
- 打开您的 info.plist 作为源代码并添加这些行:
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>
- 将此添加到您的 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))
}
}
}
如果你真的需要它,只需将@main 更改为@UIApplicationMain,它应该可以解决问题。
结合@the.blaggy 和@Ugo Marinelli 的回答,我通过修改我的 AppDelegate 使其工作,而无需创建新的 SceneDelegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(
_: UIApplication,
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = UIHostingController(
rootView: ContentView()
)
self.window = window
window.makeKeyAndVisible()
return true
}
}
我也像@the.blaggy 那样包装了我的主要结构。