我正在研究 BNR 的 iOS 编程书籍的第 7 章,但遇到了问题。在本章开始时,我设置了一个 UIViewController (HypnosisViewController) 和一个响应上一章中的运动事件的 UIView (HypnosisView)。
我在 AppDelegate.m 文件中创建 UIViewController:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
HypnosisViewController *hvc = [[HypnosisViewController alloc] init];
[[self window] setRootViewController:hvc];
...
}
在 HypnosisViewController 中,我将 HypnosisView 设置为第一响应者:
- (void)loadView
{
// Create a view
CGRect frame = [[UIScreen mainScreen] bounds];
HypnosisView *view = [[HypnosisView alloc] initWithFrame:frame];
[self setView:view];
[view becomeFirstResponder];
}
在 HypnosisView 中,我确保向 canBecomeFirstResponder 返回 YES。不幸的是,HypnosisView 没有像以前那样响应运动事件。当我最终继续前进时,我有了一个有趣的发现。如果我将 HypnosisViewController 移动到 UITabBarController 中,HypnosisView 就会开始响应运动事件。代码看起来像这样:
HypnosisViewController *hvc = [[HypnosisViewController alloc] init];
UITabBarController *tabBarController = [[UITabBarController alloc] init];
NSArray *viewControllers = [NSArray arrayWithObjects:hvc, <insert more objs here>, nil];
[tabBarController setViewControllers:viewControllers];
[[self window] setRootViewController:tabBarController];
当 HypnosisViewController 设置为 RootViewController 时,为什么 HypnosisView 没有成为第一响应者?为什么一旦 HypnosisViewController 被放置在另一个 Controller 中它就开始工作?我对 RootViewController 缺少什么?
谢谢!
最佳答案
你的问题很恰当。我也在学习同一本书并且在同一章上。问题是,在使用 UITabBarController 之前,我们要么使用 HypnosisViewController,要么使用 TimeViewController。然后我们将在 AppDelegate.m 文件中执行 [self.window setRootViewController:hvc] 或 [self.window setRootViewController:tvc] 。在这种情况下,setRootViewController 方法在内部调用 loadView 方法。因此,如果应该调用 loadView ,那么也应该触发BecomeFirstResponder(根据您的代码,它作为方法调用驻留在其中)。所以内部 canBecomeFirstResponder 应该被调用 现在,当我们使用 UITabBarController 时,事情往往会崩溃。发生的情况不是通过“[[self window] setRootViewController:tabBarController];”调用 loadView行代码,它通过“[tabBarController setViewControllers:viewControllers];”调用。所以底线是 rootViewController 属性(当设置为 tabBarController 时)不会调用 loadView 方法,因此不会调用“becomeFirstResponder”。您可能会争辩说 loadView 确实是通过“[tabBarController setViewControllers:viewControllers];”调用的但 setViewControllers 不用于设置根 viewController。 当我遇到这个问题时,我显式调用了becomeFirstResponder。方法如下:-
@implementation HypnoTimeAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions //method of UIApplicationDelegate protocol
{
NSLog(@"lets begin");
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
HypnosisViewController *viewController= [[HypnosisViewController alloc] init];
TimeViewController *viewController2= [[TimeViewController alloc] init];
NSLog(@"view controllers are done initializing!");
UITabBarController *tabBarController= [[UITabBarController alloc] init];
NSArray *viewControllers= [NSArray arrayWithObjects:viewController,viewController2, nil];
[tabBarController setViewControllers:viewControllers];//loadView of HypnosisViewController gets called internally since the 'app view' isn't going to load from a XIB file but from 'HypnosisView.m'.loadView method of TimeViewController loads its own view from the XIB file.
[self.window setRootViewController:tabBarController];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
@implementation HypnosisViewController
-(void)loadView{
NSLog(@"HypnosisView loading...");
HypnosisView *myView= [[HypnosisView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.view= myView;
[self configureFirstResponder];//configuring first responder
}
-(void) configureFirstResponder{
BOOL viewDidBecomeFirstResponder= [self.view becomeFirstResponder];
NSLog(@"Is First Responder set as HypnosisView? %i",viewDidBecomeFirstResponder);
}
关于ios - 当父 UIViewController 设置为 RootViewController 时,UIView 不会成为第一响应者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10036310/