我正在写BNR的iOS编程书的第7章,我遇到了一个问题。 在本章的开头,我设置了一个UIView控制器(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];
}
在催眠视图中,我确保将"是"返回为canBebeResponder。 不幸的是,催眠视图没有像以前那样对运动事件做出反应。 当我最终继续前进时,我有一个有趣的发现。 如果我将 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被放置在另一个控制器中,它就会开始工作? 关于 RootViewController,我缺少什么?
谢谢!
你的问题非常贴切。我也在学习同一本书,并且在同一章。问题是,在使用UITabBarController之前,我们要么使用HypnosisViewController,要么使用TimeViewController。然后,我们将在AppDelegate.m文件中执行[self.window setRootViewController:hvc]或[self.window setRootViewController:tvc]。在这种情况下,setRootViewController 方法在内部调用 loadView 方法。因此,如果应该调用 loadView,那么成为第一响应者(根据您的代码作为方法调用驻留在其中)也应该被触发。所以在内部可以成为第一响应者应该被调用 现在,当我们使用UITabBarController时,事情往往会中断。发生的情况不是通过代码行"[[self window] setRootViewController:tabBarController];"调用loadView,而是通过"[tabBarController setViewControllers:viewControllers];"调用。因此,底线是rootViewController属性(当设置为tabBarController时)不调用loadView方法,因此不会调用"bebe成为FirstResponder"。你可能会争辩说,loadView确实是通过'[tabBarController setViewControllers:viewControllers]'调用的,但setViewControllers不用于设置根视图控制器。 当我遇到这个问题时,我明确呼吁成为第一响应者。方法如下:-
@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);
}