首页 » iOS编程基础:Swift、Xcode和Cocoa入门指南 » iOS编程基础:Swift、Xcode和Cocoa入门指南全文在线阅读

《iOS编程基础:Swift、Xcode和Cocoa入门指南》9.3 编辑与代码导航

关灯直达底部

Xcode编辑环境的很多地方都可以修改以满足你的需要。首先应该在Xcode的Fonts & Colors首选项窗格中选择喜欢的源码编辑器字体和大小。没什么是比舒服地阅读和编写代码更重要的事情了!我喜欢稍大点(13、14,甚至是16)和等宽字体,如Menlo、Consolas或免费的Inconsolata(http://levien.com/type/myfonts/)与Source Code Pro(https://github.com/adobe-fonts/source-code-pro)。

Xcode提供了一些自动格式化、自动输入与文本选择特性。其行为取决于你在Xcode的Text Editing首选项窗格的Editing and Indentation页签中的设置。这里并不打算详细介绍这些设置,但建议你充分利用它们。在Editing下,我习惯勾上所有选项,包括行号;可见的行号在调试时是非常有用的。在Indentation下,我也习惯勾上所有选项;我发现在这些设置下,Xcode能以最佳的方式显示代码。

如果喜欢Xcode的智能语法感知缩进,但却发现有时会有一行代码并没有正确缩进,那么请选择Editor→Structure→Reindent(Control-I组合键),这会自动缩进当前行或所选文本。

勾选“Enable type-over completions”后,Xcode会自动加上分隔符。比如,假设我通过调用初始化器init(frame:)来创建一个UIView。我会这么写:


let v = UIView(fr  

Xcode会自动追加上右圆括号,同时插入点还在右圆括号之前:


let v = UIView(fr)// I have typed ^  

不过,这个右圆括号是试探性的;其颜色是灰色。现在输入参数;输入完后右圆括号依然是灰色的:


let v = UIView(frame:r)// I have typed ^  

现在可以通过几种方式来确认右圆括号:可以输入一个右圆括号,也可以按下Tab键或向右的方向键。这时,试探性的右圆括号会被实际的替换掉,插入点位于其之后了,准备接受后续输入。双引号、右花括号以及右方括号的行为与之类似。

9.3.1 自动补令

在编写代码时,你会用到Xcode的自动补令特性。Cocoa类型名与方法名非常冗长,无论什么,只要能节省你输入代码的时间都是好事。然而,我并没有选中Editing下面的“Suggest completions while typing”;相反,我勾选了“Use Escape key to show completion suggestions”,当我希望自动补令时,我会手工实现,通过按下Esc键。

比如,我要通过代码创建一个警告框。我需要输入UIAlertController(按下Esc会弹出一个菜单,列出适合UIAlertController的4个初始化器,如图9-2所示)。可以在菜单中导航、关闭它或接受所选,只需使用键盘即可。如果默认情况下没有选中,那么我会通过向下的方向键导航到title:...,然后按下回车键将其选中。

图9-2:自动补令菜单

从自动补令菜单中选择后,所选方法调用的模板就会输入代码中(这里将其分解为多行显示):


let alert = UIAlertController(    title: <#String?#>,    message: <#String?#>,    preferredStyle: <#UIAlertControllerStyle#>)  

<#...#>中的表达式是占位符,展示了每个参数的类型;它们在Xcode中就像是“文本标记”一样(如图9-2所示),防止你不小心修改。可以通过Tab键或Navigate→Jump to Next Placeholder(Control-/组合键)选择下一个占位符。这样就可以选择一个占位符,然后在上面输入想要传递的实参;接下来选择下一个占位符并输入其实参,以此类推。要想将占位符转换为一般的字符串且没有分隔符,可以将其选中并按下回车键,或双击它。

自动补令与上下文智能感知可用于对象类型名、方法调用与属性名。在输入函数声明时,如果这个函数是继承下来的,或定义在所使用的协议中,那也可以使用自动补令。你甚至都不需要输入起始的func;只需要输入方法名的前几个字母即可。比如,在我的应用委托类中,我会输入:


applic  

如果按下了Esc键,那么我会看到一个方法列表,比如,application:didFinishLaunchWithOptions:,这些是可以发送给应用委托的方法(第11章将会介绍)。如果选择了一个,那么其整个声明都会输入进来,包括花括号:


func application(application: UIApplication,    didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?)    -> Bool {        <#code#>}  

代码占位符位于花括号之间,它会被选中,等待着我开始输入函数体。如果函数需要一个override标识,那么Xcode的代码补令特性会提供的。

9.3.2 代码片段

代码片段是代码自动补令的有益补充。代码片段就是个带有缩写的一段文本。代码片段保存在代码片段库中(Command-Option-Control-2),不过代码片段的缩写对于代码补令却是全局的,因此可以使用片段而无须打开库:输入缩写,片段的名字就会出现在代码补令中。

比如,要想在文件顶部输入类的声明,我会输入class并按下Esc键来打开自动补令,然后选择“Swift Class”或“Swift Subclass”。按下回车键后,模板就会出现在代码中:类名与父类名是占位符,同时还有花括号,声明体(位于花括号中)则是另一个占位符。

要了解代码片段的缩写,需要打开其编辑窗口(在代码片段库中双击代码片段)并单击Edit。如果觉得记住代码片段的缩写太麻烦,可以将其从代码片段库中拖曳到文本中。可以通过过滤栏(Edit→Filter→Filter in Library,Command-Option-L组合键)根据名字快速找到所需的代码片段。

可以添加自己的代码片段,它会划分到User代码片段类别中;最简单的方式就是将文本拖曳到代码片段库中。然后编辑它以适应自己的需要,给它起个名字,提供一段说明和一个缩写;可以通过Completion Scopes弹出菜单缩小代码补令所显示的片段上下文。在代码片段文本中,使用<#...#>结构来构造任何所需的占位符。

比如,我创建了一个插座变量代码片段,如下所示:


@IBOutlet var <#name#> : <#type#>!  

我又创建了一个动作代码片段,如下所示:


@IBAction func <#name#> (sender:AnyObject!) {    <#code#>}  

我编写的其他代码片段构成了一个个人的辅助函数库。比如,delay代码片段会插入dispatch_after包装器函数(参见11.10节)。

9.3.3  Fix-it与实时语法检查

Xcode的Fix-it特性会针对如何避免问题给出一些积极的建议。要弹出它,请单击左边栏的问题标记。编译后如果有问题会显示出这种问题标记。

比如,图9-3顶部显示我不小心丢掉了方法调用后的圆括号。这会导致编译错误,因为我设置的backgroundColor属性是个UIColor,它不是函数。不过,错误旁边的停止图标告诉我Fix-it有个建议。单击这个停止图标,图9-3底部显示了发生的事情:弹出一个Fix-it对话框,告诉我该如何修复这个问题,即插入圆括号。此外,Xcode也告诉我如果Fix-it按照这种方式修复了问题,那么代码会变成什么样子。如果按下回车键,或双击对话框中的“Fix-it”建议,Xcode就会插入圆括号,错误会消失不见,因为问题已经得到了解决。

如果相信Xcode的做法是正确的,那么请选择Editor→Fix All in Scope(Command-Option-Control-F组合键),Xcode会实现周围所有的Fix-it建议,并且不会再弹出对话框。

图9-3:带有Fix-it建议的编译错误

实时语法检查像是一种持续不断的编译。即便没有编译或保存,它也可以检测到存在的问题,并且通过Fix-it给出建议的解决方案。可以通过General首选项窗格中的“Show live issues”复选框打开或关闭该特性。

我觉得实时语法检查会影响代码编写过程。在编写过程中,代码几乎不可能是合法的,因为单词与圆括号总是半成品;我准备输入这些内容!比如,仅仅输入let的首字母就会导致语法检查器报告无法解析的标识符错误;我非常讨厌这一点。因此,我并没有勾选“Show live issues”复选框。

9.3.4 导航

开发Xcode项目需要在多个文件中同时编辑代码。幸好,Xcode提供了多种方式来导航代码。前几章已经介绍了一些。下面是Xcode提供的一些主要的导航方式:

项目导航器

如果你记得文件名的一部分,那么就可以在项目导航器(Command-1组合键)中快速定位到该文件,通过在导航器底部过滤栏中的搜索框内搜索即可(Edit→Filter→Filter in Navigator,Command-Option-J组合键)。比如,输入story就会列出.storyboard文件。此外,在使用完过滤栏后,你可以按下Tab键,然后通过向上、向下的方向箭在项目导航器中导航。这样,只通过键盘就能找到所需的文件了。

符号导航器

如果高亮显示了过滤栏中的前两个图标(前两个是蓝色的,第3个是暗色的),那么符号导航器就会列出项目的对象类型及其成员。单击符号可以在编辑器中跳转到其声明。与项目导航器一样,过滤栏中的搜索框可以帮助你跳转到想要去的地方。

跳转栏

代码编辑器的跳转栏的每个路径组件都是个菜单:

底部

跳转栏底部(最右边)是文件中对象与成员声明的列表,按照它们的显示顺序排序(按住Command键的同时选择菜单可以按照字母表顺序查看);可以选择其一进行导航。

可以通过起始单词为MARK:的注释将加粗的章节标题添加到底部菜单中。比如,修改Empty Window项目中的ViewController.swift:


// MARK: - view lifecycleoverride func viewDidLoad {    super.viewDidLoad}  

结果就是底部菜单中的viewDidLoad会位于view lifecycle之前。要在菜单中创建分隔符,请输入一条MARK:注释,其值是连字符;在上述示例中,连字符(创建一个分隔符行)与标题(创建一个加粗标题)都用到了。与之类似,以TODO:和FIXME:开头的注释都会出现在底部菜单中。

上部

上部路径组件是个层次化菜单;这样你就可以通过它们遍历文件层次了。

历史

每个编辑器窗格都记得你曾经编辑的文件名。向后与向前这两个三角形既是按钮也是弹出菜单(或选择Navigate→Go Back和Navigate→Go Forward,分别对应Command-Control-Left与Command-Control-Right组合键)。

相关条目

跳转栏中最左侧的按钮会弹出相关条目菜单,这是与当前文件相关的一个层次化的文件菜单,比如,父类与所使用的协议等。该列表甚至还包含了当前所选函数调用或被它调用的函数。

跳转栏中的路径组件菜单是可以过滤的!打开跳转栏菜单,输入文本来过滤菜单所显示的信息。此处的过滤使用了“智能”搜索而不是严格的文本包含搜索;比如,输入“adf”会找到application:didFinishLaunchingWithOptions:(如果位于菜单中)。

辅助窗格

可以通过辅助窗格同时身处两处(参见第6章)。按住Option键并导航会在辅助窗格而非主编辑器窗格中打开文件。辅助窗格跳转栏中的Tracking菜单会设定其与主窗格的自动化关系。

页签与窗口

还可以通过打开页签或单独的窗口而同时身处两处(参见第6章)。

跳转到定义

可以通过Navigate→Jump to Definition(Command-Control-J组合键)跳转到代码中所选符号的声明位置处。

快速打开

可以通过File→Open Quickly(Command-Shift-O组合键)打开一个对话框,并在这里搜索代码和框架头文件中的符号。

断点

断点导航器会列出代码中的所有断点。Xcode缺少代码书签,不过可以将禁用的断点当作书签。本章后面将会介绍断点。

9.3.5 查找

查找是导航的一种形式。Xcode提供了全局查找(Find→Find in Project,Command-Shift-F组合键),这与使用查找导航器的效果是一样的;还提供了编辑器级别的查找(Find→Find,Command-F组合键);不要搞混了。

查找选项是非常重要的。对于编辑器级别的查找,请单击搜索域中的放大镜图标来打开Edit Find Options条目。可以搜索单词中间部分或单词开头,指定是否区分大小写等,甚至可以使用正则表达式进行查找。这里有大量的功能!全局查找选项位于搜索框上下,它包含了一个范围,用于指定搜索哪些文件:单击当前范围可以看到Search Scopes面板,可以选择不同的范围或创建自定义范围。

搜索框上方的全局查找选项包含了文本、正则表达式、定义(定义符号的地方)与引用(使用符号的地方)。Xcode 7新增了调用层次查找选项,可以向后追踪代码中的调用关系。单击搜索栏中的第2个条目会显示一个弹出菜单,选择Call Hierarchy即可;此外,还可以在代码中选中一个词,然后选择Find→Find Call Hierarchy(Shift-Control-Command-H组合键)。调用层次会显示在查找导航器中(如图9-4所示)。

要替换文本,请单击搜索栏最左侧的Find来弹出菜单,然后选择Replace。可以将单词出现的所有位置都替换掉(Replace All),或在查找导航器中选择特定的搜索结果,然后只替换这些(Replace);还可以从查找导航器中删除搜索结果,从而使其不会被Replace All所影响。查找导航器的Preview按钮会弹出一个对话框,展示了每个可能的替换的效果,可以在执行替换前接受或拒绝特定的替换。对于编辑器级别的查找,在单击Replace All前按下Option键,这样查找与替换就只会对所选文本起作用。

比较复杂的一种编辑器级别的查找形式是Editor→Edit All In Scope,它会在相同范围内同时查找所选文本所有出现的地方;可以通过它在范围内修改变量或函数的名字,或查看名字是怎么使用的。

图9-4:查找导航器中的调用层次