You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Game Maker扩展开发:如何在.mm中重写UIViewController方法禁用通知栏?

Game Maker: Studio iOS扩展禁用顶部通知栏拖动的解决方案

问题根源

你遇到的'NotificationBar' cannot use 'super' because it is a root class错误,本质是找错了方法所属的父类:viewDidLoad和preferredScreenEdgesDeferringSystemGestures是UIKit框架下UIViewController(视图控制器)的专属方法,而NSObject作为Objective-C的根类,根本没有这些方法,自然无法通过super调用父类实现。

正确实现方案

Game Maker: Studio的iOS应用底层基于UIKit构建,游戏画面由内置的视图控制器渲染。要禁用顶部边缘的系统手势(拉出通知栏),你需要通过**方法替换(Method Swizzling)**修改游戏主视图控制器的行为,而非创建一个无意义的NSObject子类。

具体代码实现

以下是可直接用于.mm文件的代码:

#import <UIKit/UIKit.h>
#import <objc/runtime.h>

@interface NotificationBarDisabler : NSObject
@end

@implementation NotificationBarDisabler

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 替换preferredScreenEdgesDeferringSystemGestures方法
        [self swizzleMethodForClass:[UIViewController class]
                     originalSelector:@selector(preferredScreenEdgesDeferringSystemGestures)
                     swizzledSelector:@selector(custom_preferredScreenEdgesDeferringSystemGestures)];
        
        // 替换viewDidLoad方法,补充额外设置
        [self swizzleMethodForClass:[UIViewController class]
                     originalSelector:@selector(viewDidLoad)
                     swizzledSelector:@selector(custom_viewDidLoad)];
    });
}

// 封装方法替换的工具函数
+ (void)swizzleMethodForClass:(Class)class
             originalSelector:(SEL)originalSelector
             swizzledSelector:(SEL)swizzledSelector {
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    
    // 若原方法不存在,先添加空实现
    BOOL methodAdded = class_addMethod(class, originalSelector,
                                       method_getImplementation(swizzledMethod),
                                       method_getTypeEncoding(swizzledMethod));
    
    if (methodAdded) {
        class_replaceMethod(class, swizzledSelector,
                           method_getImplementation(originalMethod),
                           method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

// 自定义的手势延迟逻辑:禁用顶部边缘的系统手势
- (UIRectEdge)custom_preferredScreenEdgesDeferringSystemGestures {
    return UIRectEdgeTop;
}

// 自定义的viewDidLoad:保留原有逻辑的同时补充设置
- (void)custom_viewDidLoad {
    // 调用原视图控制器的viewDidLoad实现
    [self custom_viewDidLoad];
    
    // iOS 11+ 额外配置,确保全屏手势行为符合预期
    if (@available(iOS 11.0, *)) {
        self.view.insetsLayoutMarginsFromSafeArea = NO;
        if (self.navigationController) {
            self.navigationController.navigationBar.prefersLargeTitles = NO;
        }
    }
}

@end

扩展入口设置

在扩展的入口函数中,只需触发类加载即可自动执行方法替换:

// 供Game Maker调用的扩展函数
void DisableTopNotificationBar() {
    // 触发类加载,+load方法会自动执行
    [NotificationBarDisabler class];
}

注意事项

  • 版本兼容性:preferredScreenEdgesDeferringSystemGestures仅支持iOS 11及以上版本,代码中已做版本判断。
  • 方法替换范围:上述代码会全局替换所有UIViewController的方法,若担心影响GMS内部其他页面,可改为仅替换游戏主视图控制器的方法:通过[[UIApplication sharedApplication] keyWindow].rootViewController获取主控制器,再针对该实例替换方法。
  • 测试验证:打包GMS项目后,需在真机上测试顶部拖动行为,确保通知栏不会被拉出,同时游戏的其他交互不受影响。

内容的提问来源于stack exchange,提问作者Nick Blackwood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:53:15