是否可以在 Mac Catalyst 中使用全屏?

Lim*_*ean 9 fullscreen uiwindow ios mac-catalyst

将游戏移植到 macOS Catalyst,但窗口很小。是否可以全屏启动?

Les*_*ary 10

是的,可以全屏启动。

方法 #1(从 Mac Catalyst 应用程序使用 AppKit 的更通用方法)

要切换到全屏,您需要使用 AppKit 和 NSApplication 类,但目前无法直接在 Mac Catalyst 应用程序中使用。但是,您可以从另一个插件包访问它。这是你如何做到这一点,并在应用程序启动时切换到全屏:

第 1 步。您需要在您的应用程序中创建一个新的 mac 包目标。单击文件 -> 新建 -> 目标 -> macOS -> 捆绑包,然后单击下一步按钮。输入产品名称,例如 MacBundle,然后单击按钮完成。

Step 2.在你的项目中选择新创建的MacBundle组,点击File -> New -> macOS -> Cocoa Class,点击Next按钮。输入类名,例如 MacApp,它是 NSObject 的子类,并将语言设置为 Objective-C。单击下一步,确保选择了 MacBundle 目标,然后单击按钮创建。

步骤 3.像这样编辑 MacApp.h:

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface MacApp : NSObject

+ (void)toggleFullScreen;

@end

NS_ASSUME_NONNULL_END
Run Code Online (Sandbox Code Playgroud)

步骤 4.像这样编辑 MacApp.m:

#import "MacApp.h"

@implementation MacApp

+ (void)toggleFullScreen {
    [[[[NSApplication sharedApplication] windows] firstObject] toggleFullScreen:nil];
}

@end
Run Code Online (Sandbox Code Playgroud)

步骤 5.单击您的项目并在 Targets 部分选择您的主要应用程序目标(与 iOS 相同)

步骤 6.在 General 选项卡中向下滚动到 Frameworks、Libraries 和 Embeded Content 部分,然后单击 + 按钮。在用于选择框架的新弹出窗口中,选择 MacBundle.bundle 并单击“添加”按钮以将此包嵌入到您的主应用程序中。

第 7 步。现在您可以从您的主要 iOS 代码的 MacBundle 中的 MacApp 类调用 toggleFullScreen 方法。为了使其工作,您可以从应用程序中出现的第一个 UIViewController 的 viewDidAppear 调用一次它。你可以像下面这样称呼它:

static var needsFullScreen = true

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    
    if Self.needsFullScreen {
        Bundle(path: Bundle.main.builtInPlugInsPath?.appending("/MacBundle.bundle") ?? "")?.load()
        let macApp = NSClassFromString("MacApp") as? NSObjectProtocol
        macApp?.perform(NSSelectorFromString("toggleFullScreen"))
        Self.needsFullScreen = false
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用该 toggleFullScreen 方法创建协议。

之后,当您启动应用程序时,它会自动切换到全屏模式。

方法#2(对于这种特定情况,不太通用但速度更快)

如果您不打算使用其他 AppKit 的东西,那么对于前面方法中显示的这个 toggleFullScreen 调用,您可以只调用它,而无需使用运行时函数的插件包,从出现在您的应用程序中的第一个 UIViewController 的 viewDidAppear 调用一次,如下所示:

static var needsFullScreen = true

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    
    if Self.needsFullScreen {
        (NSClassFromString("NSApplication")?.value(forKeyPath: "sharedApplication.windows") as? [AnyObject])?.first?.perform(Selector("toggleFullScreen:"))
        Self.needsFullScreen = false
    }
}
Run Code Online (Sandbox Code Playgroud)


rma*_*ddy 3

没有简单的设置说“开始全屏”。但您可以在启动时设置窗口的框架。

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let _ = (scene as? UIWindowScene) else { return }

    #if targetEnvironment(macCatalyst)
    window?.frame = CGRect(origin: .zero, size: CGSize(width: 1600, height: 1000))
    #endif
Run Code Online (Sandbox Code Playgroud)

显然这并不理想,因为您不想对特定大小进行硬编码。

您可以按如下方式获取屏幕尺寸。但根据我自己的测试,返回值并不准确。这可能是 Mac Catalyst 中的一个错误。

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let winScene = (scene as? UIWindowScene) else { return }

    #if targetEnvironment(macCatalyst)
    let screen = winScene.screen
    let size = screen.nativeBounds.size
    window?.frame = CGRect(origin: .zero, size: size)
    #endif
}
Run Code Online (Sandbox Code Playgroud)

这使它更大,但它并不是真正的全屏,因为至少在我的测试中,返回的屏幕尺寸实际上与屏幕尺寸不匹配。

但这应该会给你一些想法。

您还可以设置屏幕上的最小和最大尺寸:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let winScene = (scene as? UIWindowScene) else { return }

    #if targetEnvironment(macCatalyst)
    if let sizes = winScene.sizeRestrictions {
        let screen = winScene.screen
        let size = screen.nativeBounds.size
        sizes.minimumSize = size
        sizes.maximumSize = size
    }
    #endif
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,屏幕的大小不会调整,因为最小值和最大值相同。进行调整以满足您的应用程序的需求。如果您为最小值和最大值指定不同的值,如果您希望初始大小介于最小值和最大值设置之间,则还可以将其与设置窗口框架结合起来。


下面是 Objective-C 中的相同解决方案:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let _ = (scene as? UIWindowScene) else { return }

    #if targetEnvironment(macCatalyst)
    window?.frame = CGRect(origin: .zero, size: CGSize(width: 1600, height: 1000))
    #endif
Run Code Online (Sandbox Code Playgroud)