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
相关产品推荐
相关产品推荐

