Window

Application在收到触控等硬件事件之后,会把事件转发给key window。如果你iOS SDK问世的前几年就在写iOS App,应该会注意到,Xcode帮你建立Project时使用的template中,可能就有一段像下面这样的-application:didFinishLaunchingWithOptions的实现:

- (BOOL)application:(UIApplication *)application
  didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    ViewController *controller = [[ViewController alloc] init];
    self.navigationController = [[UINavigationController alloc] initWithRootViewController:tabBarController];
    window.rootViewController = self.navigationController;
    [window makeKeyAndVisible];
    return YES;
}

当一个window被调用了-makeKeyAndVisible之后,就会变成key window。但这样的解释还是很模糊—到底什么是key window?要回答这个问题,我们要先离开一下iOS SDK,来看看Mac。

在Mac 上,一个window 除了可以是key window 之外,还可以成为main window。比方说,TextMate 这套文字编辑器是一套Document-based App,我们可以同时开很多window,每个window 里头都代表一份文字档案,但是,我们一次也只能在一个window 当中打字,所以,只有一个window 的边框会是比较深的颜色,其他window 的边框则是浅色,代表这些window 没有作用。唯一作用中的window 就是main window。

但假如我们现在调出了TextMate 的寻找功能,想要在目前正在编辑的文字档当中,寻找指定的文字,这时候键盘焦点会放在搜寻window 的关键字栏位上。现在搜寻功能window 就是key window。Key window 所谓的key,其实就是键盘keyboard 的key,你在哪个window 打字,那个window 就是key window。而由于我们是对现在正在编辑的文件做搜寻,所以我们在搜寻window 这个key window 打字之后,会再去寻找main window,把进行搜寻这件工作送往main window。

很多时候main window 与key window 会是同一个。比方说,我们找到了关键字,离开了搜寻window,回到主要文件window 打字,那么,这份文字档的window 就同时是main window 与key window。

在iOS 上,由于每个App 主要只有一个处理事件的window,因此没有需要区分main window 与key window,因此SDK 的设计上就只有key window,而没有main window。

其实iOS App 可以拥有多个window。在苹果推出AirPlay 功能,让iOS App 的画面可以投射到AppleTV 之后,除了两边完全镜像之外,我们也可以选择在AppleTV 的画面上显示不一样的内容,像Keynote 这套App 在连接到AppleTV 之后,可以选择AppleTV 上是目前所在的简报页面,iOS 装置上则显示下一页投影片方便提词,实作方式就是建立第二个Window,然后选择把第二个window 放在AppleTV 上。但是在AirPlay 的状况下,AppleTV 的画面只有显示的功能而已,我们并不会在这个window 中打字。

在另外一个情境下,我们也可能会想要建立自己的window。在不少App中,其实有使用一项UI设计:在画面上方的status bar部分,额外显示提示讯息,使用status bar message当关键字在github上搜寻,就可以看到至少有MTStatusBarOverlayFDStatusBarNotifierViewJDStatusBarNotification这么多个Projects。

其实iOS的status bar本身就是一个window,而这个window的level会比我们App的window高,于是status bar会一直叠在我们的App画面上方,不论我们对原本的window怎么增加subview,都不会影响status bar。如果我们想要盖过status bar,方法就只有建立新的window,level设得比status bar window更高,然后调用makeKeyAndOrderFront,让这个window出现在屏幕上。

这时候我们要千万注意:makeKeyAndOrderFront不但会让这个window出现,同时也变成key window,所有的事件都会往这个window送。所以,如果提示讯息结束,我们必须要对原本的key window再呼叫一次makeKeyAndOrderFront,把处理事件的权力交还回去,不然接下来我们的App就无法处理任何事件了。

当我们在iOS App的一个画面上,如果有很多文字框(UITextField),我们想要指定其中一个文字框拿来打字,会调用becomeFirstResponder,让这个文字框变成first responder,具体来说的意义是「这个window上的first responder」。这点在Mac的API上会比较清楚,如果在Mac的一个window中要指定某个文字框打字,我们不是对NSTextField调用,而是对window呼调用makeFirstResponder:,然后传入text field。

results matching ""

    No results matching ""