iOS Objective-C全局悬浮按钮实现中loadView未调用的原因及解决方案
Hey there! Let's figure out why your ApplicationFloatingButtonController's loadView method isn't being called when you're trying to build a global floating button in iOS with Objective-C. Here's a breakdown of possible causes and actionable fixes:
- Your custom window isn't properly linked to its root view controller: If
ApplicationFloatingButtonWindowdoesn't haveApplicationFloatingButtonControllerset as itsrootViewController, or the window isn't activated, the controller's lifecycle methods (includingloadView) won't trigger at all. - The window isn't added to the app's window hierarchy: In iOS, a window needs to be made visible (
hidden = NO) and part of the app's active window stack for its associated view controller to initialize. - No strong reference to the window: If your
ApplicationFloatingButtonWindowinstance is a local variable, ARC will automatically release it, so the controller never gets a chance to load. - Typos or incorrect implementation in
loadView: A misspelled method name (likeLoadViewwith a capital L) or missing setup in the controller can also prevent the method from being called.
1. Properly Configure the Custom Window and Link the Controller
Update your ApplicationFloatingButtonWindow.m to correctly initialize the controller, set it as the root, and configure the window to be visible:
@implementation ApplicationFloatingButtonWindow - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Set window level to ensure it sits above all other windows self.windowLevel = UIWindowLevelAlert + 1; // Make the window visible self.hidden = NO; // Initialize and attach the root view controller ApplicationFloatingButtonController *floatingBtnVC = [[ApplicationFloatingButtonController alloc] init]; self.rootViewController = floatingBtnVC; } return self; } @end
2. Keep a Strong Global Reference to the Window
To prevent the window from being released by ARC, hold onto it in your app's entry point:
For AppDelegate (pre-iOS 13):
In AppDelegate.h:
@property (strong, nonatomic) ApplicationFloatingButtonWindow *floatingButtonWindow;
In AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Initialize the floating window with full screen bounds self.floatingButtonWindow = [[ApplicationFloatingButtonWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; return YES; }
For SceneDelegate (iOS 13+):
In SceneDelegate.h:
@property (strong, nonatomic) ApplicationFloatingButtonWindow *floatingButtonWindow;
In SceneDelegate.m:
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { self.floatingButtonWindow = [[ApplicationFloatingButtonWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; }
3. Verify Your Controller's loadView Implementation
Double-check that the method is correctly implemented in ApplicationFloatingButtonController.m—no typos, and proper view setup:
@implementation ApplicationFloatingButtonController - (void)loadView { // Create the base view for the controller self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.view.backgroundColor = [UIColor clearColor]; // Keep it transparent so it doesn't block underlying content // Add your floating button here UIButton *floatingBtn = [UIButton buttonWithType:UIButtonTypeCustom]; floatingBtn.frame = CGRectMake(20, 200, 60, 60); floatingBtn.backgroundColor = [UIColor systemRedColor]; [floatingBtn setTitle:@"Tap" forState:UIControlStateNormal]; [self.view addSubview:floatingBtn]; } @end
4. Debug with Logs (If Needed)
If you're still stuck, add debug logs to your window's init method to confirm everything is configured correctly:
NSLog(@"Root VC attached: %@", self.rootViewController); NSLog(@"Window hidden: %d", self.hidden); NSLog(@"Window level: %f", self.windowLevel);
Ensure the root view controller isn't nil, hidden is NO, and the window level is higher than standard windows (UIWindowLevelNormal).
- On iOS 13+, make sure you're handling window setup in
SceneDelegateinstead ofAppDelegateif your app uses the scene-based architecture. - Be mindful of touch interactions—your floating window might block taps on underlying views, so you can override
hitTest:withEvent:inApplicationFloatingButtonWindowto pass through touches that aren't on the button.
内容的提问来源于stack exchange,提问作者Bocato

