【问题标题】:How to disabled fullscreen button on MacCatalyst如何在 Mac Catalyst 上禁用全屏按钮
【发布时间】:2020-01-15 10:06:11
【问题描述】:

目前,我有这个停止调整窗口大小:

#if targetEnvironment(macCatalyst)
windowScene.sizeRestrictions?.minimumSize = CGSize(width: 480, height: 900)
windowScene.sizeRestrictions?.maximumSize = CGSize(width: 480, height: 900)
#endif

let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()

全屏 按钮无论如何都会使其全屏显示。

【问题讨论】:

    标签: swift macos swiftui mac-catalyst


    【解决方案1】:

    这是另一种不需要 Objective-C、选择器或异步调用的方法。它也不需要目标宏,iOS 将简单地跳过if let NSApplication。将其粘贴到首先出现的视图控制器中。请注意,这会禁用所有窗口上的绿色全屏按钮。如果您想与众不同,请使用 Asperi 的 Swift 部分的想法。

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    
        func bitSet(_ bits: [Int]) -> UInt {
            return bits.reduce(0) { $0 | (1 << $1) }
        }
    
        func property(_ property: String, object: NSObject, set: [Int], clear: [Int]) {
            if let value = object.value(forKey: property) as? UInt {
                object.setValue((value & ~bitSet(clear)) | bitSet(set), forKey: property)
            }
        }
    
        // disable full-screen button
        if  let NSApplication = NSClassFromString("NSApplication") as? NSObject.Type,
            let sharedApplication = NSApplication.value(forKeyPath: "sharedApplication") as? NSObject,
            let windows = sharedApplication.value(forKeyPath: "windows") as? [NSObject]
        {
            for window in windows {
                let resizable = 3
                property("styleMask", object: window, set: [], clear: [resizable])
                let fullScreenPrimary = 7
                let fullScreenAuxiliary = 8
                let fullScreenNone = 9
                property("collectionBehavior", object: window, set: [fullScreenNone], clear: [fullScreenPrimary, fullScreenAuxiliary])
            }
        }
    }
    

    【讨论】:

    • 为什么苹果要求我们做这些事情?您的代码是否通过了 Mac App Store 审核?基本上它可以工作。
    • @MarcT。我这样做的 Catalyst 应用程序是在 Objective-C 中的,上面仅来自我的 Swift 测试项目。是的,然后它反复通过了 Mac App Store 的审查。为什么他们要求它,为什么他们不提供方法来做他们所要求的,这是任何人的猜测。
    • 这很棒,你有 let resizable = 3 我把它改成了 4 当他们点击绿色按钮时,它会变成我设置的最大尺寸,而不是全屏,因为当它是3 无法调整大小。不知道这些数字是什么意思,我尝试了几个数字,直到找到我喜欢的。
    • @KurtLane Here 是 3 的文档(实际上是 1NSPanel 的子类,我不确定这在 Catalyst 上下文中意味着什么。
    【解决方案2】:

    这有点复杂,但可能。这是一种方法(我删除了所有目标宏以简化帖子)。

    结果:

    代码:

    // on next event after UIWindow has made key it is possible to find NSWindow in runtime
    
        func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    
            ...
            window.makeKeyAndVisible()
    
            DispatchQueue.main.async { // < wait for NSWindow available
                SilentBridge.disableCloseButton(for: self.nsWindow(from: window))
            }
        }
    
    // added helper function to SceneDelegate to find NSWindow
    
        func nsWindow(from window: UIWindow) -> NSObject? {
            guard let nsWindows = NSClassFromString("NSApplication")?.value(forKeyPath: "sharedApplication.windows") as? [NSObject] else { return nil }
            for nsWindow in nsWindows {
                let uiWindows = nsWindow.value(forKeyPath: "uiWindows") as? [UIWindow] ?? []
                if uiWindows.contains(window) {
                    return nsWindow
                }
            }
            return nil
        }
    

    Objective-C 部分是首选(使用未声明的选择器更简单)。通过 Xcode 模板添加新的 Objective-C 类并确认创建桥。之后需要在生成的*-Bridging-Header.h 中添加下面的类头文件,一切都应该工作。

    // SilentBridge.h
    
    @import Foundation;
    
    @interface SilentBridge : NSObject
    + (void)disableCloseButtonFor:(NSObject  * _Nullable)window;
    @end
    
    // SilentBridge.m
    
    #import "SilentBridge.h"
    @import Foundation;
    
    // Forward declarations to allow direct calls in below method
    @interface NSObject(SilentBridge) 
    - (id)standardWindowButton:(NSInteger)value;
    - (void)setEnabled:(BOOL)flag;
    @end
    
    @implementation SilentBridge
    
    + (void)disableCloseButtonFor:(NSObject *)window {
        if ([window respondsToSelector:@selector(standardWindowButton:)]) {
            id closeButton = [window standardWindowButton:2];
            if ([closeButton respondsToSelector:@selector(setEnabled:)]) {
                [closeButton setEnabled:NO];
            }
        }
    }
    @end
    

    【讨论】:

      猜你喜欢
      • 2013-01-27
      • 2020-02-18
      • 1970-01-01
      • 2020-02-19
      • 2021-02-18
      • 2015-10-05
      • 1970-01-01
      • 1970-01-01
      • 2017-03-31
      相关资源
      最近更新 更多