大纲:编程
1.iOS的系统发展服务器
从1983年OC程序开始发展到2015年,30多年的时间,但这依然不是一个十分完善的语言,能够说如今都没有一个十分完善的,不用更新了的编程语言。可是,iOS选择了OC做为它的开发语言,这是为何咱们前期须要先来学习OC语言的缘由。那其实以前咱们学习的都是一些开发的必备知识,并无接触任何的软件开发的知识。从今天开始才是真正的开始接触开发。咱们知道市面上先有iOS、Android、Window Phone这三大移动平台。Windows Phone在国内是什么待遇呢?相信大家关注支付宝的人,应该听过1%的梗,window phone的用户要支付宝更新,结果支付宝发了一个微博说“你为何选择1%的生活”,是说的它占有量不到1%,其实我是很是喜欢微软的,个人第一个智能手机是WP7.0,我还有XBox、surface设备。那还有Android和iOS的开发,Android是如今占有量最大的一个移动平台,大家用Android手机的人,应该新的旗舰级就还好,若是是通常的或者是之前的手机,那必定有一个反应就是,慢慢的手机变卡了。若是你接触智能手机时间比较早的话,你当时买的Android2.3的手机如今是都不能够升级到4.0以上了吧。而Android的一个变革时期就是4.0以后,优化好了不少。它这个硬件限制软件更新的方法,我以为是回让他牺牲必定的用户量的,毕竟没有人但愿看到本身去年买的手机,今年就不被支持了吧。可是上面咱们说的事情,苹果就处理的比较好。再咱们开发人员上面,Android的开发配置方面咱们须要作的环境搭建,十分复杂,你光是作这个搭建开发环境的事情估计就须要半天了,可是咱们这个iOS开发,到如今为止,作了什么来搭建环境啊?仅仅只是安装了一个XCode吧。实际上作开发的时候呢,其实这些都无伤大雅。综上所述呢,咱们这个作iOS开发会比其余的有必定的优点。但一样,咱们作这个的成本相对前二者就要高一点了,无论是买一个Mac仍是安装一个黑苹果。架构
作iOS的开发,先要了解一下iOS这个系统的发展。从iOS7这以后,都是摆脱了以前乔布斯的一个理念,不只是从硬件方面,他的屏幕尺寸一点点的变大,还有它的整个拟物化的UI风格变成了一个扁平化的设计。这个都是如今iOS的一个发展趋势。因此咱们了解他如今的一个界面的风格,也是咱们之后对软件开发很重要的一块。咱们能够来看看如今的一个真机上的样式。app
左边这个界面,就是咱们如今iOS9.2最新版本的一个界面,咱们看到了它上面的软件图标排列,就像是把一个个的软件放到棋盘格子里面了吧。框架
咱们回忆一下,五子棋的棋盘是否是一个个90°的笔直的角,而咱们看到这个软件的图标样式,是否是一个圆角的样子,这个已经被苹果注册了专利——圆角矩形。包括它的文件夹都是这个效果。编程语言
那咱们再仔细一点看,看每个图标的样子。是否是每个都是很简单的图形,没有不少很炫的效果。都像一个个瓷砖贴屏幕在上面?这其实是iOS7以后,力推的一个扁平化效果,和iOS7以前的一个拟物化效果彻底不一样。拟物化咱们顾名思义,就是模仿现实生活中的物品来作的一个效果。好比之前的日历应用就是一本日历的样子,而且每个都有阴影效果,显得很像现实生活中的东西同样。其实这个扁平化的历史很好玩,他是由谷歌的一个工程师提出来的概念,可是微软是第一个使用扁平化做为移动平台界面的公司,苹果呢,能够说是如今把扁平化效果作的最出色的一家公司。以致于有不少的消费者认为苹果是这个扁平化概念的提出者。这个扁平化咱们要好好地记住了。ide
为何咱们要了解苹果如今的风格呢?其实我我的以为最主要的一点,由于,你不能在控件列表中,找到之前的样式了,本身来作那种样式UI的话,麻烦的不是一点点。再者,苹果对按照他当前最新样式来开发的软件,只要你内容能够,那么会有一个在app store里面上内推榜的机会。这是一个推广本身软件的好机会。函数
那咱们再来看看这个时钟应用的内部,咱们之后作的事情是来开发吧。看看这个官方的应用,咱们看看一个应用由什么来组成。左上角的“编辑”和右上角的“+”号,是否是一个按钮啊?它能够被点击的,而且相应事件,是一个按钮啊。那咱们再看中间有“世界时钟”几个字吧,这其实就是个字符串对不对。一样地道理,下面“北京”、“今天”、“柏林”等等这些东西都只是一些字符串吧。那在咱们UI阶段,有专门放置字符串的控件,让他可以放到这个界面上面。每个时钟,实际上是个图片,咱们也有专门的控件来放图片。那最底下那些东西,其实也是一些按钮了吧。因此咱们能够看到,作一个软件仍是很简单的啊。工具
那你们能够看到,iOS原生的应用都有一个固定的设计风格,并无一个应用一个大相径庭的风格吧。其实苹果不只是对本身出得软件的界面风格有要求,他对全部在app store上架的都要求符合如今的一个界面风格要求,保证本身整个商城的生态环境。这也是与Android最大不一样的地方。那要符合这样一个设计风格,就要体现一个UI设计师的功底,和咱们的关系就不是太大。可是说回来,若是一个APP的界面作的很丑,那用户也不会对这个软件买帐啊,天然就发展不起来。说道这个用户,咱们也讲一下app的这个商业盈利模式,像一些免费软件,它都有一些内购的东西吧,好比说每一年WWDC大会上面,一些免费得软件或者游戏。那些收费的软件就更不用说了吧,直接找你要钱的嘛。不过相比内购,我是更喜欢付费应用的。苹果如今是全球市值最高的公司,他会作一个只用来让人们方便下东西,让咱们来赚钱的商城么,毕竟服务器的开销也不小!那他本身是怎么赚钱的呢?经过一个拥有高质量用户群体的app store,拉动开发者为他开发软件,其中每个app的下载,他就从中抽取30%,有好的应用就会有更多的人进入到这个生态圈,更多的用户,那就会有更多好的开发者进入到这里面来,这是一个完美的环。仅2014年一年,开发者经过app store赚取了150亿美圆,其中就有45亿美圆落入了apple的口袋。如今大家能够想一想这个app store的价值。布局
2.UI介绍
以前学习的都是开发的一个语言基础,不会这个编程语言,咱们是没有办法在以后的工做中进行一个开发的,咱们说学UI就是学习搭建一个程序的界面,若是你没有学习这个编程语言,那也是没有办法写出一个逻辑。这是咱们以前为何要学习OC的缘由。那咱们OC学了这么久,咱们还有人想对着那个只能打印字符的控制台一生么?若是有的话,那你不适合作一个软件的开发,却是能够去尝试下作一个后台的开发啊~那什么东西叫UI呢?User Interface这样一个词组的缩写,翻译过来“用户界面”,国外有的大学有专门的课程叫UI交互设计、UI设计等等,证实这个UI他也不是一个很简单的东西,否则也不会有这么多的课程专门来说这个啊,可是咱们对UI的使用就很简单,直接用别人总结出来的东西就能够了~可是咱们要了解这个东西,怎么去使用别人的劳动成果。
咱们学习UI究竟是在学习什么呢?相信大家还记得OC里面咱们学的Foundation框架,在UI阶段,咱们也有一个框架,叫作UIKit,它也为咱们封装了不少方法,能够直接进行一个操做。比方说咱们能够直接使用他,来响应一个用户的点击或者触摸,能够在屏幕上显示咱们想要的内容,好比一个文字或者图片,相对应的系统的相机、麦克风等等设备咱们均可以进行一个调用。那相应的UIKit框架的使用,咱们后面会一步一步来为你们讲解。咱们以前说了iOS的一个系统架构是分红了4层,最下面的Core OS,Core Service,Media和Cocoa Touch层,相比咱们如今使用的Mac OS系统,实际上是在Cocoa框架上面封装了一层Cocoa Touch层。也是和咱们操做息息相关的一层,咱们UI阶段要学习的就是Cocoa Touch 、Media层的使用。它里面包含了咱们UI阶段使用最多的UIKit框架,还有地图、联系人、信息等等都是这个框架下的。还有Media层中也是咱们要用到的,像播放音频视频、绘图就是Media层中来实现的。Core Service主要是包含咱们以前学的Foundation框架,Core OS是最靠近底层的一层,咱们使用的机会基本上没有了。
3.简单App讲解
A.iOS现行设备尺寸、像素规范
咱们如今开发的是iOS操做系统,用的最多的就是iPad和iPhone两个设备,其实都是差很少的,咱们如今就先来看看iPhone的开发
仍是像之前同样,咱们开始新建一个工程,可是!咱们再也不是选OS X里面的命令行工程了,而是像上面显示的,咱们找到iOS这个选项,选择他下面的Application,那咱们就会看到有上面几个选项,第一个是在iPad上面会用到的,他有一个侧边栏能够选择。第二个是一个有分页效果的页面,能够左右滑动。第三个是单个页面的应用。第四个是带有一个标签栏,就像上面咱们看的时钟应用,下面的按钮能够跳转到不一样的一个页面。那最后一个就是Game,我就不说了。在咱们学习过程当中,使用最多的是第三个,也是我选中的Single View Application。
那咱们像之前同样,点击Next,而后创建一个工程。这里咱们先创建一个名字叫作test的Single View Application工程。
那咱们能够看到咱们如今看到的不是像之前只有一个.m文件了,而是多了APPlication和ViewController这两个类,还出现了两个咱们历来没有看到过的,一个Main.storyboard和一个Launchscreen.storyboard文件,咱们等下会来介绍这个东西,讲这个东西有什么用。咱们来选中Main.storyboard文件,看看他是什么样子。
这是一个正方形的图形,它是否是有点像一个平板的屏幕啊?比咱们的手机屏幕要宽一些,长一些。storyboard顾名思义是一个故事板,storyboard就像一张白纸,你能够在上面写故事,什么意思呢?你能够在上面画任何你想要它显示的东西,咱们可使用这个工具对页面进行一个布局,想要在什么位置显示什么东西,拖相应的控件上去就行,这就是咱们所谓的可视化开发。在日后的工做中,若是须要赶进度,使用这个工具,它甚至可让界面的开发时间减小一倍。
咱们先什么都不干,直接运行一次这个程序。仍是和之前同样,咱们按快捷键command+R。咱们发现,有一个应用程序自动运行了,咱们作iOS开发,你作项目,必须运行在iOS设备上面,那咱们在开发阶段,使用模拟器来进行调试工做,当你项目比较完善以后,咱们就使用真机来测试。那这就是一个iPhone的模拟器,咱们如今看到的这个界面是一个彻底空白的软件界面,内容上和咱们以前看到的storyboard文件是彻底一个样子。那咱们默认运行的设备应该是iPhone6,在你的项目名旁边能够看到一个设备的名称,点击以后,就能够选择不一样的模拟器来运行你的程序。那咱们如今要记住的是一个现有的设备的尺寸,和逻辑分辨率这一栏。这对于咱们往后进行一个开发是十分重要的数据。
设备 iPhone |
宽 Width |
高 Height |
对角线 Diagonal |
逻辑分辨率(point) |
Scale Factor |
设备分辨率(pixel) |
PPI |
3GS |
2.4 inches (62.1 mm) |
4.5 inches (115.5 mm) |
3.5-inch
|
320x480 |
@1x |
320x480 |
163 |
4(s) |
2.31 inches (58.6 mm) |
4.5 inches (115.2 mm) |
3.5-inch |
320x480 |
@2x |
640x960 |
326 |
5c |
2.33 inches (59.2 mm) |
4.90 inches (124.4 mm) |
4-inch |
320x568 |
@2x |
640x1136 |
326 |
5(s) |
2.31 inches (58.6 mm) |
4.87 inches (123.8 mm) |
4-inch |
320x568 |
@2x |
640x1136 |
326 |
6 |
2.64 inches (67.0 mm) |
5.44 inches (138.1 mm) |
4.7-inch |
375x667 |
@2x |
750x1334 |
326 |
6+ |
3.06 inches (77.8 mm) |
6.22 inches (158.1 mm) |
5.5-inch |
414x736 |
@3x |
(1242x2208->) 1080x1920 |
401
|
那从整个界面上咱们还能发现一个东西,照道理来讲,这个界面应该是一个全白色的,那如今它上面多了一些数据。并且咱们能够看到Carrier(运营商),有个WiFi标志。中间有一个时间,这个时间是咱们电脑的系统时间,最右边是电量图标。这个东西呢,咱们称之为状态栏,他在iOS7.0以前都是一个不透明的效果,是一个单独存在于屏幕上的东西,可是如今,他是透明的,怎么说呢?你能够看到他如今是一个白底黑字,你能够尝试将整个背景设置为黄色、绿色或其余的颜色,就会看到一个很明显的效果了。
那咱们如今来尝试在界面上面,加入一些东西。咱们点开main.storyboard文件,看看右下角
第一个是一些文件,好比建立类能够直接从这里拖出去就建立了一个类。
第二个是一些代码段。
第三个是一个(Object-Library)资源库,这里有不少的控件能够供咱们来选择。但咱们如今不会用到里面全部的控件,咱们在以后的学习中会一点点的来学习。
第四个是媒体库。
B.作一个简单的加法计算器。
这里来尝试使用storyboard作一个简单加法计算器,上面是咱们最后的成品效果图。点开main.storyboard文件,在右下方的资源库中,找到这样一个控件。按住它,向storyboard上面拖过去,当storyboard变成蓝色以后,咱们松开手,是否是上边多出了一个显示着Label字样的标签,接下来双击拖出来的这个控件,如今他就能够被编辑了,咱们在上面打上“简易加法计算器”,点击一下旁边,取消这个编辑效果。能够看到它显示的样子并非咱们所但愿的,那咱们再次单击这个控件,此次控件上出现了
8个锚点,咱们先拖动右下方这个锚点,能够看到,字一点点的能够显示出来了。咱们将这个调整到合适的大小,顺即可以尝试一下其余几个锚点,看看效果。咱们看效果图上面,还有“+”、“=”和“0.00”几个控件,这些都是可使用刚才这个控件来进行实现的吧。尝试改变他们的位置和大小,让它看起来更美观。
咱们再次看到右下方的资源库中,单击这个Label控件,咱们能够看到旁边出现了一个对话框。那红色框起来的地方,UILabel是这个控件的类,表明什么,他是一个UILabel类控件吧,记住它,对之后代码编程的时候会颇有用。
最下方还有一个能够点击的“计算”按钮,那按钮顾名思义Button吧,这里由UIButton控件来完成所需。依然是将Button拖到storyboard上面,可是咱们看到并无上图的蓝底白字的效果,打开右侧边栏,选中第四个像游标卡尺一些样的三角按钮,出现了不少选项可让咱们调整。将Text Color改成白色,View中的background改成蓝色
。如今就有了上面效果图的效果了吧。
一样地还有两个能够输入内容的地方,咱们使用UITextField控件来完成,你们能够本身在资源库中找找。顺便试一下其余的控件都有什么用处。
运行一下,能够看到如今咱们的界面已经作好了。可是这个程序有任何的效果嘛?无论咱们点击什么,都没有任何的反应吧。那接下来,就要给它建立他的逻辑。
那想要代码和图形可以结合起来,XCode为咱们提供了一个开发界面,使咱们方便操做。点击右上角的辅助编辑按钮,咱们发现有了两个能够操做的开发界面,一个是显示的storyboard,一个显示的是代码。那这个有什么用呢?如今,按住你电脑上的control按钮,不要放手,用鼠标按住storyboard区中的“计算”按钮,向代码区拖动,有没有发现多出了一根蓝色的线,咱们一直将鼠标移动到类扩展区域,看到代码区多了一根横线,这时,松开鼠标和键盘就行。
松开鼠标后,看到弹出了一个对话框
第一行Connection中有三个选项,第一个是默认的Outlet,这个中文就是出口的意思。能够想象咱们有一个管道,让咱们把东西从楼上运到楼下,那咱们在管道的出口处等着拿东西就能够了吧~一样,想要获取到这个控件的信息,信息就从楼上运过来,咱们找到这个管道的出口,是否是就能够拿到控件信息了,经过这个咱们能够拿到控件属性。第二个是Action,动做,使用这个会产生一个新的方法,在响应用户交互时,会执行方法中的代码。第三个Outlet Collection,顾名思义一个属性的集合。这里咱们选择Outlet。第二行的对象所属,是个不可选择的。第三行Name,要咱们为这个属性或者这个方法取一个别名,这里取名calculatorButton。第四行Type中,是咱们这个对象的类型,以前拖拽控件的时候咱们就看到了,这里会是UIButton。最后的Storage,持有类型,这个控件在拖到storyboard上面的时候,就被这个视图有一个Strong持有,保证它存在于堆中,因此在外部,咱们不须要一个Strong指针指向它。若是这个控件从视图中离开,那么,他就会被从堆中清除,这个指向控件的指针就会变为咱们想要的nil,由于向nil发送一个消息,程序是不会崩溃的。大部分状况下,这里都是使用Weak。最后按下Connect按钮或者敲下回车。
本来什么都没有的类扩展中,忽然就出现了一段代码。仔细看,和咱们之前写类的属性的时候,十分的相像吧。可是这里多了一个IBOutlet,实际上对编译器没有任何的用处,只是告诉XCode,我和其余的东西有关联。你能够本身写一个属性,而后给他加上IBOutlet关键字,前面都会多出这个形状。如今咱们把鼠标移到这个圆上面,是否是发现,storyboard上面,“计算”这个按钮亮了起来,这就是告诉咱们,这个代码已经和storyboard相关联了。
咱们有输入框,要拿到输入框中的信息是否是同样须要给两个输入框拖线?还有最后用来显示结果的Label也是须要的吧。咱们给他们分别取名text1,text2,resultLabel。
点击这个计算按钮,程序也应该要有反应,这里就是再次对Button拖线,但选择再也不是Outlet,而是刚才说过的Action了。咱们看到Action的返回类型是IBAction,这个其实就是void类型。
1 @interface ViewController () 2 3 //计算按钮 4 @property (weak, nonatomic) IBOutlet UIButton *calculatorButton; 5 //按钮计算方法 6 - (IBAction)calculator:(id)sender; 7 8 //第一个输入框 9 @property (weak, nonatomic) IBOutlet UITextField *text1; 10 //第二个输入框 11 @property (weak, nonatomic) IBOutlet UITextField *text2; 12 13 //结果Label 14 @property (weak, nonatomic) IBOutlet UILabel *resultLabel; 15 16 17 @end
如今咱们来分析下如何编写点击按钮的方法。第一,咱们要拿到输入框中的数字,UITextField中就为咱们提供了相应的属性--text,使用self.text1.text,咱们就能够拿到text1输入框中的内容。text2也是同样的道理。咱们点到UITextField类中能够看到,text属性是一个什么类型啊?NSString吧,咱们能不能直接把字符串拿来相加?明显是不能够的,使用floatValue的getter方法,咱们就能够将它转化成数字了吧。那咱们有了计算的结果,就要将结果显示在界面上了,UILabel也有text属性,可是NSString要怎么才能显示一个float的基础数据类型呢?要用到Foundation框架中stringWithFormat:方法了吧。而后将这个NSString赋给Label的text属性就能够了是否是?下面就是实现的代码。
1 - (IBAction)calculator:(id)sender { 2 if (self.text1.text.length != 0 && self.text2.text.length != 0) { 3 self.resultLabel.text = [NSString stringWithFormat:@"%.2f", self.text1.text.floatValue + self.text2.text.floatValue]; 4 } else { 5 NSLog(@"Error, No Input"); 6 } 7 }
如今一个简单地加法计算器就作完了,这也是咱们第一个iOS程序。
4.视图的生命周期
说过全部的这些简便的东西,其实是他背后无数行代码的一个实现,那咱们也可使用代码来作。可是这一课咱们不讲如何使用代码来作上面的简易计算器。咱们介绍一下之后代码写在哪里。
那咱们说C语言程序启动是从main函数这个入口函数进去,展开左侧边栏中的Supporting Files文件夹,main.m文件就在这里,可是咱们不在这个地方写代码。说到哪里写以前,咱们先看到程序的main函数,函数有入口是否是就有出口,执行完return中的函数,就return对不对,可是这里由于这个函数,致使main函数return不了。那这个函数前面两个参数是一些系统信息,第三个是一个nil,其实是一个默认指定的UIApplication类,最后一个就是把程序的启动代理给获取到的类名,关于这个参数能够本身去研究一下。那函数其实是帮咱们建立了一个UIApplication对象和AppDelegate的对象,并将程序代理给AppDelegate对象,而且调用了AppDelegate中的方法。咱们看到系统是默认帮咱们建立了AppDelegate类吧,点进去,看到下面这个方法就是被代理调用的协议方法。
1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 2 // Override point for customization after application launch.
3 return YES; 4 }
咱们看这个代码,其实啊,作这个iOS的开发,其实英语好的颇有优点,为何这么说呢?didFinishLaunching这个是完成启动的意思,他在程序已经启动完以后,就会到这个方法里面来。后面咱们会知道有方法,能够在程序启动以前对程序进行一些设置。咱们之后写代码直接到这个方法里面写。
那还有其余的一些代理方法,咱们能够来看一看。一个程序开始运行了,是否是就像激活了一个设备,设备开始运转,咱们这里也有一个相同的协议方法:程序进入激活状态,是活动的。这个在程序每次在运行的时候都会调用。
//进入到活动状态 - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. NSLog(@"Become Active"); }
有激活天然有一个非激活状态,何时会是一个非激活的状态呢?咱们双击Home键,你会发现控制台就打印了“Resign Active”
//程序进入到非活动状态 - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. NSLog(@"Resign Active"); }
那咱们知道,有双击Home键的操做,固然有单击Home键的操做吧。咱们按一下Home键,其实是进入了一个后台。咱们能够看到,控制台此次打印了“Resign Active”和“Did Enter Background”。咱们在执行锁屏、接电话等操做的时候都会进入到这个后台,那进入后台和非激活状态是不同的啊。但你进入了后台,那就必定是非激活的状态。
//程序进入后台 - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. NSLog(@"Did Enter Background"); }
进入了后台,咱们点击这个程序图标,还能回到这个程序,一样地一个回到前台的代理方法。
//进入前台 - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. NSLog(@"Will Enter Foreground"); }
最后咱们看到,还有一个程序终止的代理方法。这个是咱们退出程序的时候会调用到的一个方法,为了防止程序意外退出咱们没有保存一些信息。可是这个方法只在程序运行的时候才会调用,若是咱们这个程序已经进入了后台,退出程序的话,会不会调用这个方法?是不会的啊。
//程序退出 - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. NSLog(@"Terminate");
这些东西,咱们如今先用做了解。你们如今知道,何时会调用什么东西就行。
今天最重要的,是咱们要掌握如何使storyboard和代码间建立一个联系。能够多去本身尝试一下。那下面有一些经常使用的XCode快捷键,你们能够记一下
(1)Xcode快捷键 主界面: Command + R 运行 Command + . 中止运行 Command + B 编译 Command + H 隐藏Xcode Command + N 新建文件 Command + shift + N 新建工程 Command + O 打开文件 Command + 数字键(1-8) navigator栏 Command + 数字键0 隐藏navigator栏 Command + Y 开启控制台 Command + option + 0 开启/隐藏utilities栏 Command + return 标准模式 Command + option + return 辅助编辑模式 代码: Command + control + 方向键 .h/.m文件切换 Command + [ 向左缩进 Command + ] 向右缩进 Command + option + [ 上移 Command + option + ] 下移 Command + Y 开启断点 Command + \ 加入断点 Command + K 清空控制台 文档: Command + ‘+’ 放大 Command + ‘-’ 缩小 Command + ‘=’ 适应