我们在练习(一)中完成了状态栏图标点击,弹出内容视图的效果,但是项目看起来还有些体验不是非常符合用户习惯,(例如点击应用之外的其他地方,popover 并没有自动消失)我们继续来添加和完善一些用户功能,使得应用看起来有好一点的使用体验,接下来我们为popover添加鼠标的事件监听和退出应用的功能。
为了响应系统的鼠标事件,我们需要使用Cocoa框架中的NSEvent类来为应用添加监听对象,在Mac 开发中,通常我们都是被(鼠标或键盘)事件驱动的,当OSX系统接收到一个事件后,会添加到窗口服务进程的处理队列中,然后通过服务进程异步的派发事件(事件可能会被copy)给应用程序,应用程序会通过delegate响应对应的事件。
应用程序在响应事件的过程中,会生成一个monitor(监听)对象,通常情况下我们完成监听事件后,不必对这个对象进行手动释放,系统API会在合适的时机进行release。
1.1 选中ViewController.m文件,添加鼠标左键点击事件监听,实现代码如下图:
运行应用,点击状态栏图标显示popover后,用鼠标点击应用窗口外的其他地方,这时你会发现popover会自动隐藏起来了,这样的效果与之前的相比,要更合适操作一些。除此之外,我们继续为popover 添加一个button,来实现退出应用的功能。
1.2 选中SBPopViewController.xib文件,添加button,并设置入下图:
1.3 选中SBPopViewController.m,为button添加事件响应代码如下图:
再次运行应用,如果没有错误,点击状态栏图标,界面大概样子应该入下图:
点击退出按钮,你会发现应用将结束进程并退出。现在我们这个应用可以实现显示popover,并点击应用之外的地方可以隐藏popover,并可以手动退出应用,这些基本功能已经都完成了,但从项目开始到现在,window窗口一直都伴随每次启动显示(它在我们这个应用看起来没什么用处),针对我们只设计一个在系统状态栏的demo应用来说,window是可以不要的,那么我们来对window进行处理。
1.4 选中Main.storyboard文件,从项目中删除,并清空工程配置,入下图:
如果这时你运行工程,会发现之前的window不显示了(因为已经删除了嘛),但是状态栏的图标也没有显示,应用运行起来,但桌面没有任何我们需要的效果,这时我们在打开活动监视器,发现应用其实是正常运转的(如下图)。
这是由于我们之前使用的xib文件加载window,系统为我们默认做了一些其他方面的事,比如再加载window之前,创建应用对象,设置应用代理,配置窗口设置等,那系统是在哪里做的这些事情呢?其实是在main.m文件里的调用了系统的NSApplicationMain()这个重要的函数,这个函数屏蔽了很多细节,这对新入门的来说是件好事,可以很容易的进行业务代码的工作而不必关系系统启动的细节;但如果我们需要研究系统在启动时的一些行为时,它也给我们带来了难度。
像iOS中一样,应用启动加载完成后,设置UI是从AppDelegate的这个方法-applicationDidFinishLaunching:开始的,如果我们在上面的工程中对这个方法设置调试断点,你会发现应用启动后,根本没有调用这个方法,也就是所我们删除了main.storyboard文件后,系统不再自动的为我们设置应用的delegate,需要我们自己手动在main.m中进行设置。
1.5 选中main.m文件,实现代码入下图:
1.6 因为我们去除了window,因此ViewController对我们来说已经没有价值了,我们只需要把之前在ViewController中写的代码,放置到AppDelegate.m中来实现就可以了,这样我们就可以删除ViewController这个类了。项目修改后的样子应该是下面这个图的的示例:
如果你在这中间的步骤没有错误,那么再次运行工程,你会发现状态栏的上图标又出现了,并且我们之前实现的功能也都可以正常响应了^_^
整个工程的代码,可以从这里下载StatusBarDemoApp,好了,我们这个小练习工程介绍完了,算是为新上手Mac OSX开发的同学略微做些基础帮助,由于笔者的能力有限,如果在这个小练习工程中有错误的地方,还请各位随时回复我,或在评论里告知,这样也可以让其他人看到,共同进步。
结束语
项目小练习只是一个学习的开始,大家可以对这个小练习再添加一些功能:比如菜单栏,比如设置开机自动启动,再或者运行后隐藏Dock上的图标,对代码结构再进行合理的组织,比如把事件监听的方法,封装为一个工具类,或者使用tableview代替SBPopViewController,添加网络请求数据等,这样就可以由这个小练习慢慢变成自己的一个小Mac 应用了,祝各位能有所收获~。