iOS UI开发捷径——利用Interface Builder高效、优雅地开发UI(txt+pdf+epub+mobi电子书下载)


发布时间:2020-08-02 18:18:18

点击下载

作者:郭晓亮

出版社:电子工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

iOS UI开发捷径——利用Interface Builder高效、优雅地开发UI

iOS UI开发捷径——利用Interface Builder高效、优雅地开发UI试读:

前言

F O R E W O R D

iOS系统在移动互联网如火如荼、方兴未艾的发展中有着举足轻重的地位,iOS开发也成为近几年比较热门的行业。UI开发是iOS开发中重要的一部分,不仅负责信息的展示,还可以与用户交互,直接体现出应用程序的“颜值”,影响着用户体验,所以说UI开发相当重要。对于已开发的应用程序,用户并不关心开发人员用了哪些技术和解决方案,只关心页面做得是否好看,交互操作是否顺手,滑动时会不会卡,这些都与UI开发息息相关。在实际的开发工作中,UI开发往往占据了大部分的时间和精力。而我们所追求的是快速开发UI,把主要精力放在业务逻辑上,这也是苹果公司所希望的,因此,苹果公司将Interface Builder作为UI开发的“大杀器”,并在逐步地改良。这本书讲的就是如何利用Interface Builder高效、优雅地开发UI。

写作的动机

从技术角度来讲,UI开发主要有两种方式:

1.利用代码开发。

2.利用可视化开发工具——Interface Builder开发。

在实际的工作中,大部分情况是将两种方式结合使用。但是在国内,Interface Builder的应用相对于国外来说并不是特别广泛,使用的场景相对简单,使用的技术也比较浅,并没有展示出Interface Builder强大的功能和应有的价值。Interface Builder在国内是一项被低估的技术。在2015年苹果全球开发者大会(WWDC)的“What’sNew in Storyboard”会场中,苹果公司的演讲嘉宾现场统计了使用Interface Builder开发者的人数,从他的言语中可以推测,当时国外开发者中使用Interface Builder的比例已经相当高了。从侧面可以看出,在iOS开发上,我们和国外的开发者还有一定的差距。

随着4.0英寸、4.7英寸、5.5英寸iPhone手机的出现,适配成了UI开发中很烦琐的一件事情,对于要适配横屏、竖屏或iPhone与iPad通用的应用程序尤为如此。利用Interface Builder+Auto Layout+TraitVariations可以十分简单、高效地解决这个问题。苹果公司每个新版本的Xcode都会对Interface Builder进行相应的功能升级,而且从苹果公司每年在WWDC上推出的新技术来看,很多是与Interface Builder相关的。这也说明,使用Interface Builder是UI开发的大势所趋。

在程序员看来,没有什么自动化是一个脚本解决不了的,如果有,那就是再写一个脚本。但通常来说,程序员都喜欢追求效率,而Interface Builder对开发效率的提升无疑是巨大的。

笔者希望通过这本书能够让国内的开发者重新认识Interface Builder,对Interface Builder产生浓厚的兴趣,最后达到精通Interface Builder的目的。同时希望开发者能将其更多地应用到实际开发中,提高自己的工作效率,从而更加从容地面对互联网行业紧张、快速的节奏。笔者不才,如果本书对你来说没能达到期望的效果,那么只希望它能对你学习Interface Builder起到一个抛砖引玉的作用。

本书的特点

本书的特点如下。

1.细致。本书每个知识点的讲解都力争做到细致,让Interface Builder零基础的iOS开发者可以在入门时更加从容。如果你是有一定Interface Builder基础的开发者,那么可以略过一些自认为琐碎的细节,以免浪费宝贵的时间,但是如果你有兴趣了解这些细节的话,也一定会有所收获,它会让你更加系统、更加深刻地掌握Interface Builder。

2.全面。本书的讲解也力争做到全面,让读者可以掌握Interface Builder开发中的各种技巧,了解各个细节,并能够系统地掌握Interface Builder相关的原理。由于Interface Builder相关知识碎片化严重,体系化不明显,如果只学习在开发过程中的应用技能,不深入理解一些原理,那么在一段时间不用之后很容易遗忘,只有掌握了相关的原理,理论配上实践,才能全面地掌握它。

3.深入。本书在介绍Interface Builder的基础知识和基本使用之后,加入了大量的进阶内容,包括有些章节中的“深入学习”和“Interface Builder进阶”。这些内容绝对能在Interface Builder开发中起到至关重要的作用,相信会改变你对Interface Builder原有的认识,虽然这里介绍的很多Interface Builder的应用技巧并没有在开发中得到普遍使用,但是它们的确很方便、实用。如果能掌握这些深入的知识和技巧,那么在利用Interface Builder开发时一定会变得更高效、更优雅。

4.拓展。与此同时,本书加入了一些iOS开发中的其他知识点,一部分穿插在整本书中,另一部分则以“拓展学习”章节的形式出现,用于配合Interface Builder的讲解。Interface Builder开发与iOS其他方面的开发并不是孤立的,实际上学习Interface Builder时,需要具备很多iOS其他方面的知识,这些知识可以让读者学习Interface Builder时更轻松,更便于理解,同时也能学习得更深入。拓展部分的内容包括iOS开发中的一些基本原理和应用细节,例如App启动流程分析、UIApplication自定义、iOS开发中的内存管理、SDK开发应该掌握的一些技巧等,还包括其他方面的一些内容,例如CocoaPods和“黑魔法”——如何实现在低版本中使用高版本中才存在的类等,这些内容对大家学习Interface Builder之外的iOS开发知识非常有帮助。

5.实用。本书还会介绍一些细节,这些细节虽然很小,但是在开发中却很重要,也很实用。其中很多都是笔者自己踩过的“坑”,本书介绍的这些细节可以帮助读者避开这些“坑”,也可以从笔者个人的经验中学到一些东西。本书的最后还会介绍一些Interface Builder开发中的小技巧和笔者在使用Interface Builder时遇到的一些bug,相信这些实用的内容会给读者带来帮助。

内容的组织

本书一共分为7章。

第1章主要介绍Interface Builder、xib、Bundle、sb、nib、storyboardc等内容,理解这些内容是系统学习Interface Builder的基础。这些内容决定了理解和掌握Interface Builder的深度,所以非常重要。除此之外,第1章还介绍了Interface Builder的优缺点及其学习的特点,了解优缺点便于大家更好地使用它,同时也有利于项目中UI开发的技术选型,便于更快速地掌握它。本章最后介绍了iOS开发中的依赖管理工具——CocoaPods。

第2章首先讲解如何有效地解决Interface Builder文件的冲突。文件的易冲突是很多开发者拒绝使用Interface Builder的一个重要理由,所以本章解决了这些开发者的担忧。然后介绍如何创建并使用各种Interface Builder文件,由于在不同情况下创建和使用方式不同,所以有些细节需要特别注意。本章还讲解了Interface Builder文件与源文件的“关联”、与源文件建立@IBOutlet和@IBAction“连线”等一些基本而又重要的操作,这些操作在平时开发中经常被使用。另外还会介绍Bundle的创建,这对开发SDK很有帮助。除此之外,还介绍了App启动过程的分析和自定义UIApplication,它可以帮助大家理解App启动后是如何与代码关联的。

第3章对xib进行了全面的讲解,包括Utilities中的每个检查器菜单、各个菜单中的重要标签、控件栏中的重要控件、Show theObject library菜单(主要讲解了在xib中使用手势),以及在xib中使用tableView、tableViewCell、AssetCatalog等内容。这些都是Interface Builder开发的基础,是必须掌握的内容。

第4章将介绍Auto Layout在Interface Builder中的使用。Interface Builder的最大优势在于可以快速地开发UI,减少大量的“胶水代码”,其次就是利用Auto Layout可以高效、优雅地做适配,所以本章将详细地介绍Auto Layout在Interface Builder中的使用,讲解在不写代码的情况下,如何利用Interface Builder+Auto Layout满足产品经理刁钻的UI需求。本章首先会详细介绍Auto Layout相关的基础知识,包括Auto Layout的理解、如何正确设置约束等,然后介绍Interface Builder中Auto Layout的菜单,及其重要的标签,最后讲解Interface Builder中使用Auto Layout进行布局的实践。除此之外,还会介绍如何实现在低版本中使用高版本中才存在的类等拓展内容。

第5章全面讲解storyboard,介绍xib中没有的一些菜单和功能,其中重点讲解segue,包括常规的segue、自定义的segue、Embed Segue、Unwind Segue等,还有一部分重要的内容是在storyboard中使用tableView(包括静态tableView)和tableViewCell,这些内容都可以在xib的基础上再次提高开发效率,是storyboard的优势所在。

第6章是Interface Builder的进阶章节,主要包括用Trait Variations做适配、IB文件的加载过程、App的本地化、Storyboard Reference和RBStoryboardLink的使用、IB中Object与ExternalObject的使用、IB中关键字的总结等内容,这部分都是在平时开发中用得比较少,但很实用的内容,有一些内容比较难理解,需要上面几章的基础知识做铺垫。

第7章介绍在Interface Builder开发中的一些技巧,帮助大家提高开发效率,并讲解笔者在Interface Builder开发中遇到的一些bug。

适合的读者

本书适合以下几类读者。

1.iOS入门开发者。

使用Interface Builder是iOS入门最简单的方式,它对快速学习并掌握UIKit有事半功倍的作用,同时Interface Builder也是UI开发的趋势所在。本书并不会介绍Objective-C、Swi等开发语言,也不会介绍Foundation、UIKit等基础类库及iOS基础知识,它不是那种“从入门到精通”的工具书,但是可以配合这本书,帮助开发者入门iOS。

2.不熟悉Interface Builder,在开发中也很少使用Interface Builder的iOS开发者。

本书介绍的基础知识可以让读者应对大部分与Interface Builder打交道的情况。可能有些开发者在开发中并不使用Interface Builder,但是如果开发团队中有人在使用Interface Builder的话,有这方面的知识会让团队合作更顺畅,也更容易熟悉工程中其他人写的代码。除此之外,现在在网上下载一个Demo,几乎都是基于Interface Builder的,苹果公司官方的Demo更是这样,熟悉Interface Builder是适应开发大环境的需要。

3.想在Interface Builder上进阶的开发者。

很多人认为,Interface Builder很简单,很容易上手,根本没有可以深入学习的内容。其实,这是一种不正确的想法。Interface Builder的确很简单,很容易上手,但同时Interface Builder有很多功能并不被大多数开发者所知所用,例如,如何用Interface Builder简单地进行本地化?如何用Interface Builder优雅地实现VC间的回调传值?如何在Interface Builder菜单栏中显示一个类自定义的属性?甚至还有一些灵活的用法可以改变工程中类之间的依赖结构,一些高级的用法还可以优化工程架构,使架构更简单、耦合性更低。Interface Builder绝不仅仅停留在UI上,这里有很多内容值得大家去探索。

本书的约定

本书用UI特指User Interface——用户界面,包括与用户的交互行为,在某些语境下也指代UI设计师;用PM指代产品经理;用UE指代交互设计师。本书中提到的App特指在iOS系统上运行的一个应用程序——Application;提到的苹果特指苹果公司。

在接下来的学习中,会用IB指代Interface Builder;用sb指代storyboard。storyboard是一种文件的格式,可以理解为.storyboard格式的文件。所以,本书提到的sb就是指.storyboard格式的文件。同样,xib就是指.xib格式的文件。本书提到的IB文件就是指.xib文件和.storyboard文件。在本书中,用VC或viewController代表一个UIViewController子类的实例,在某些语境下也用页面代表VC,用view代表一个UIView类或其子类的实例。在Interface Builder中,通常用View Controller、Button和Label等指代控件区域中相应的模板,用viewController、button和label指代用这些模板生成的实例对象。本书中的OC指代Objective-C开发语言;crash指代程序运行出错。

本书使用的IDE为Xcode8.0,使用的编程语言为Swi3.0。在某些情况下,如果IB的使用在Swi和Objective-C上有不同,那么会将两者不同的用法都介绍一下。本书提到的源文件指Swi语言中的.sw i文件,或者Objective-C语言中的.h、.m文件,例如Person类的源文件,就是指Person.swi文件,或者Person.h、Person.m文件。

读者服务

轻松注册成为博文视点社区用户(www.broadview.com.cn),扫码直达本书页面。

•提交勘误:您对书中内容的修改意见可在提交勘误处提交,若被采纳,将获赠博文视点社区积分(在您购买电子书时,积分可用来抵扣相应金额)。

•交流互动:在页面下方读者评论处留下您的疑问或观点,与我们和其他读者一同学习交流。

页面入口:http://www.broadview.com.cn/31721第1章Interface Builder概要

Interface Builder(IB)源自于NeXTInterface Builder,从iOS系统的问世到现在,一直伴随着它共同发展。起初IB作为独立应用存在于Mac OSX上,从Xcode4开始则被集成到了Xcode中,成为IDE的一部分。但这不意味着苹果公司在弱化IB的功能,恰好相反,苹果公司一直在强化并改进它的功能。分析Xcode4之后的每个Xcode版本更新的内容,就会发现:每个版本的Xcode都对IB做了改进或加强。本章主要介绍IB的概念、IB中涉及的几种文件类型、使用IB开发的优缺点、IB学习的特点,以及IB的发展等。1.1 Interface Builder简介

在学习IB之前,首先要知道IB是什么,对它有一个总体认识,然后对xib、sb等文件类型有一个全面的了解。从宏观上理解这些知识,是IB学习的基础,也是重中之重。1.1.1 Interface Builder是什么

Interface Builder,是用于苹果公司Mac OSX操作系统的软件开发程序,是Xcode套件的一部分。Cocoa和Carbon开发者可以使用Interface Builder创建和修改应用程序的图形用户界面。其数据以XML的形式被储存在xib文件中。

以上是维基百科对IB的解释,可能有些抽象。简单来说,IB就是苹果公司给开发者提供的可视化UI开发工具。本书只讨论基于Cocoa touch环境的iOS开发,其他公司提供的IDE中也有可视化开发工具,但都没有IB这么强大。比如,Android开发中就有类似的工具,只是大家在实际开发中都不会去使用,因为太难用,功能也很初级。另外,Android的布局原理和iOS不太一样。

个人认为,Android的布局比iOS先进,不像iOS这样复杂、烦琐,因此UI的可视化工具意义并不是很大,而iOS为了弥补布局的复杂和烦琐,就使得Interface Builder变得十分强大、十分有用。

简单来说,它可以高效、优雅地开发并维护UI。除此之外,也可以完成很多非UI的开发工作,其功能强大到令人咋舌。

对于IB,可以这样简单地理解:IB之于程序员,就像Photoshop之于设计师,它们都是在可视化地编辑UI。1.1.2 xib是什么

xib是IB中的一种文件类型,也就是.xib扩展名的文件。xib是早期的一种文件类型,一直沿用到现在,在Xcode5中苹果大幅度简化了xib文件的格式。用IB开发UI的大部分工作都是在编辑xib或sb文件,并把它们与源文件“关联”起来,把与xib或sb相关的交互和业务逻辑写在源文件中。xib是文本文件,以XML的形式存储UI相关数据,例如:

从XML数据中可以大致看出该文件对应的UI是什么样的,例如“<rect key="f rame"x ="0.0"y="0.0"width="375"height="667"/>”和“<color key="backgroundColor"red="1"green ="0.0"blue="0.0"alpha="1"colorSpace="calibratedRGB"/>”。

xib在项目中作为资源文件存在,又和普通的图片、音频、视频等资源文件有所不同,理解这一点很重要,尤其在开发SDK时,如图1-1所示。图1-1 xib资源文件

从图中可以看出,xib是资源文件,在Copy Bundle Resources里显示。关于xib与其他资源文件的不同,笔者会在下面详细讲解。还有一点希望大家理解:xib是可以不依赖于源文件而单独使用的,纯粹的“死”UI可以只用一个xib文件显示,无须使它与源文件“关联”。虽然这种使用场景不多,但是它可以帮助我们深刻地理解xib。

对于xib,可以这样来理解:xib之于程序员,就像psd之于设计师,它们都是一种文件格式,我们的大部分工作都是在可视化地编辑这些文件。1.1.3 拓展学习:Bundle概念的理解

在开始深入学习之前,先理解iOS开发中一个很重要的概念——Bundle。

Bundle:一种标准化的层次结构,保存了可执行代码及代码所需要的资源。

这是苹果对Bundle的解释,听上去可能很抽象,简而言之,Bundle就是一个有着固定结构的目录,可以把它想象成一个文件夹,里面的文件结构是固定的,实际上也可以利用这一点来创建Bundle,后面会详细介绍。

Bundle有以下两种表现形式:

1.保存可执行代码。也就是说,我们的App就是一个Bundle。因为每个App内部的结构都是固定的,而且App这个Bundle就是在编程中经常使用的main bundle。

//在Swif t中:

let mainBundle=Bundle.main

//在OC中:

NSBundle*mainBundle=[NSBundle mainBundle];

2.保存需要的资源。这里的资源包括xib(实际上是nib)、storyboard(实际上是storyboardc)、图片、声音、视频、字体等。

添加到工程里的资源文件在编译时会被复制到main bundle中,可以在Copy Bundle Resources中查看所有被打包到main bundle中的资源文件,如图1-1所示。只有在Copy Bundle Resource中显示的文件在编译时才会被复制到main bundle中的,直接向工程中添加的资源和通过AssetCatalog方式添加的资源都会在Copy Bundle Resource中显示,而有些时候虽然向工程中添加了资源,但是在Copy Bundle Resource中可能没有显示,这时需要点击Copy BundleResource下面的“+”按钮手动添加,否则main bundle中就不会有该资源文件,在代码中使用该资源文件时可能会出问题。

如果xib文件是直接添加到工程中的,那么在编译之后就会以第1种形式存在于App这个Bundle中,这也是最常用的一种方式。如果我们的工作是开发一个SDK,那么为了方便管理资源,通常xib文件及其他资源文件都会单独打包成一个Bundle文件,这里的Bundle文件,就是上面说的第2种形式,例如在使用腾讯的SDK时会看到TencentOpenApi_IOS_Bundle.bundle文件,在使用Twitter的SDK时会看到Tw itterKitResources.bundle文件,它们都属于第2种形式,当这些SDK被其他工程使用时,编译后在App这个Bundle中就会包含TencentOpenApi_IOS_Bundle.bundle和TwitterKitResources.bundle这两个子Bund le。

在写SDK或者要把某个需求写成通用型(即可以被公司中不同项目使用)时,往往会把这个需求写成一个独立的工程。如果是SDK,那么通常会以.a或.framework的方式供别人使用;如果被公司中其他项目使用,可以使用CocoaPods来做工程间的本地依赖,这样十分方便。当然有很多开源的项目提供.a或.framework库,同时也支持CocoaPods。无论是哪种情况,只要该独立的工程涉及UI展示,那么用到的资源最好用Bundle的形式整理,这样便于使用,同时看上去简洁、一目了然。1.1.4 理解Bundle对于IB的指导意义

首先,一个IB文件编译之后对应的文件存在于main bundle中的用法,与不在main bundle中的用法有一点不同,主要体现在指定的Bundle对象不同,前者指定为main bundle,后者指定为存放IB文件的Bundle。

其次,如果App每次在显示一个页面之前就会crash,而该页面又恰好是用IB开发的,那么首先应该检查一下指定的Bundle中是否有该页面对应的IB文件编译后对应的文件,这是排查问题的首要步骤。如果发现对应的Bundle中没有该文件,那么再看看Copy Bundle Resources中有没有对应的文件,以及工程中有没有对应的文件,这种crash在很多情况下是由于对应的资源文件没有在指定的Bundle中而造成的。

笔者就遇到过一个类似的问题:笔者写了一个普通的products为.app的工程A,是以CocoaPods的方式给主工程使用的(包括源文件和IB文件),奇怪的是,主工程的App每次要展示笔者在A工程中写的一个页面时就会crash;更奇怪的是,有些同事会发生crash,有些同事(包括笔者自己)则不会发生crash。笔者分析原因,首先从IB资源加载这个点出发,发现发生crash的同事,其Xcode在run时没有把笔者A工程中页面的xib文件编译后对应的文件放在main bundle中,而没有发生crash的同事,其Xcode在run时main bundle中有xib文件编译后对应的文件。由于项目工期的原因,笔者并没有深入研究发生这种奇怪问题的原因是Xcode、CocoaPods、本地环境变量配置,还是笔者自身的原因,但是这个奇怪的问题瞬间就得到了解决,所以如果大家遇到了类似的问题,务必要先检查一下Bundle。查看main bundle比较简单的方法是,右击Xcode左边栏Products里的xxx.app,在弹出菜单中选择Show in Finder选项,在显示的Finder窗口中选中xxx,然后右键选择“显示包内容”就可以了。1.1.5 storyboard是什么

storyboard(sb)是iOS5的新特性,它提供了一种全新的方式来可视化编辑UI,最早在Xcode4.2中出现。理解了xib,再去理解sb就十分容易了。sb是基于IB的一种文件类型,也就是.storyboard扩展名的文件,sb也是文本文件。sb以XML的形式存储着UI相关数据,xib 与sb的这一特性很重要,这使得它们可以以XML的形式被查看,也为解决IB文件引起的冲突找到了一个突破口。除此之外,sb也是作为资源文件存在于Bundle中,所以前面提到的xib应该注意的问题,sb也要注意。sb可以不与源文件关联而单独使用,最典型的例子就是LaunchScreen.storyboard。

可以把sb简单理解成一组与viewController“关联”的xib集合,该集合中同时也保存了各个viewController之间跳转的数据,可以在sb文件中查看每一个viewController的布局样式、跳转关系等信息,利用sb可以自动地完成页面间的跳转,这是sb比xib更有优势的一个重要体现。sb也支持在tableView和collectionView上添加cell,这是它优势的另一个重要体现,这使得开发显示tableView的页面变得更简单了。

随着IB的逐渐发展,sb的功能也越来越强大,其开发UI的效率比xib高,大部分情况可以替代xib,之所以说大部分情况,是因为如果在开发中要使用一个纯View的话,那么最好选择xib。如果VC的UI很复杂,出于简化sb和封装的考虑,把一些UI做成xib会更好一些,比如把VC中显示的toolBar做成xib,不仅可以减轻sb的压力,而且还可以把toolBar封装起来,应用到其他页面,一举两得。

个人认为,xib可以很好地作为sb的补充。

在程序架构设计时,从大处着眼多用sb来把使用view的地方用sb做成一个VC,然后使用VC的view来呈现;从小处着眼多用xib来简化sb,并封装成一些通用型的小控件。

xib与sb的知识体系几乎相同,不同之处大多体现在sb的功能比xib多,比如在sb中使用segue、使用cell等。所以后面的学习“套路”是:先学习xib,再学习sb。当掌握了xib,再去学sb就变得很简单了,只需要学习sb特有的功能就可以了,那些与xib相同的功能,在用法上是一样的,这样就可以以最低的成本将两者系统地学习一遍。

对于sb,可以这样简单地理解:sb是xib 2.0,即它的增强版。1.1.6 nib是什么

细心的读者可能发现,我们在上面讲Bundle时,多次使用了“一个xib文件编译之后对应的文件”,这也就说明:xib文件随工程被编译之后发生了变化,并且在Bundle中生成了与之对应的文件,这个文件就是nib文件。苹果官方描述nib如下:

A nib filedescribesthevisualelementsofyourapplication’suser interface,includingwindows, views,controls,andmany others.Itcan also describenon-visualelements,such as theobjects in your application thatmanageyourwindowsand views.

大致意思是:

nib文件是描述应用外观的视觉元素,其中包含了窗口、视图、控制对象和其他元素等,它也可以描述非视觉元素,例如应用中管理窗口和视图的对象。

通常官方描述都很晦涩,这里通过另一个角度去理解nib就变得很简单了。nib的名字源自Next Interface Builder,xib是IB编辑过程中的一种文件类型,而nib是工程被编译后,由xib生成的一种文件类型。xib文件编译后要被序列化为二进制的nib文件,使用时将nib文件反序列化,就可以显示了。举例来说,假设工程中有一个Test.xib文件,该工程编译后就会在Bundle中生成一个与之对应的Test.nib文件,如图1-2所示。图1-2 Test.xib编译后变成了Test.nib

到这里就可以解释之前说的一个问题了:为什么xib在项目中作为资源文件存在,但又和普通的图片、音频、视频等资源文件有所不同。因为xib文件是需要编译的,编译之后xib就不存在了,而在Bundle中生成了与之对应的nib文件。其他资源文件在编译时仅仅被复制到Bundle中。加载图片、音频、视频等资源文件时,可以用Bundle获得对应资源的path,然后通过path,用不同的API加载不同的资源。

let path=Bundle.main.path(forResource:"Test",of Type:"png")

//通过path,加载对应的资源

...

但是不会用这种方式去加载一个xib类型的资源文件。

//这种加载方式是错误的

let path=Bundle.main.path(forResource:"Test",of Type:"xib")

如果大家刚刚开始学习IB或iOS,对此有疑问的话可以思考一下,为什么不可以。有些人会说:上面已经说过了,编译之后Test.xib被序列化为Test.nib,所以在Bundle中找Test.xib会返回nil。没错,这个想法是正确的。像下面这样获得path则是没有问题的。

//这种加载方式没问题,但是不能通过这种方式来使用

let path=Bundle.main.path(forResource:"Test",of Type:"nib")

虽然用上面的方法可以获得nib文件的path,但是仍然不能用该方法使用IB文件。上面说过:从xib到nib的过程叫序列化,但其实xib和nib都属于plist文件,plist——property list format,就是经常说的属性列表文件,plist文件有三种格式:XML、二进制格式、JSON。在Mac OSX的term inal里输入man plist可以详细地了解plist文件。经常在工程中使用的info.plist、xib、sb等文件都是XML格式的文件,但是xib经过编译之后的nib文件却是二进制的plist文件。由于苹果不允许查看并再次编辑nib文件,所以用path(forResource:of Type:)这样的代码加载IB文件是没有意义的。然而,可以用其他方式加载并使用IB文件,在第3章“全面学习xib”中会进行详细介绍。

实际上,序列化后的数据都是不能查看的,而不仅仅是nib文件,因为苹果用了自己特殊的格式对数据进行编码,所以序列化(也叫固化)之后的数据可以算是加密数据,数据安全基本上是有保障的,这也是序列化和直接写文件两种数据持久化方式的最大区别。

对于nib,可以这样简单地理解:nib是序列化的、加密的xib。1.1.7 storyboardc是什么

理解了nib,再理解storyboardc就很简单了,storyboardc就是编译后被序列化的storyboard,它与nib极其相似。概括来说,IB开发过程中的xib、storyboard属于XML格式的plist文件,当工程被编译之后,它们就变成了相应的nib、storyboardc文件。nib、storyboardc属于二进制格式的plist文件,不允许再次查看和编辑,如图1-3所示。图1-3 nib和storyboardc无法再次查看和编辑

对于storyboardc,可以这样简单地理解:storyboardc是序列化的、加密的storyboard。1.2 Interface Builder的优点

下面说一下IB有哪些优点,只有当它的优点带来的收益大于学习的成本时,才会促使大家努力学好它。而且知道了它的优点才能知道在什么情况下使用它,有利于做技术选型。优缺点是很主观的概念,以下是笔者的个人观点,仅供参考。1.2.1 开发和维护效率高

这是IB开发最大的优点,在IB中“拖”一下鼠标,就能初始化一个控件。修改控件的一个属性,就相当于写了一句设置属性的代码。而这些过程都是可视化的,所以开发效率比写代码要高很多,并且用control+c组合键进行复制、用control+v组合键进行粘贴都比代码方便、直观。大部分情况,无须运行程序,仅在IB中就可以看出UI的效果,例如横屏、竖屏不同的布局,就可以通过设置IB中的Orientation直接看效果,无须运行,十分方便、高效,但如果是纯代码开发的话,必须运行后将设备横屏,才能看出横屏的UI效果。除此之外,在IB中拖动一个控件到源文件中就可以很方便地声明一个属性,或绑定一个处理事件的方法,这种声明和绑定事件的代码由Xcode自动生成。利用IB也能很轻松地给UIView添加手势……IB还有一些“高冷”的用法,可以使一些情况的处理变得异常简单,大大提高开发效率。

对于维护来说,IB的效率也是很高的。在IB中找特定的UI控件很方便、快速,没有任何压力。但是,如果在代码中找特定的UI控件,由于不是自己写的代码,所以会很费时间。如果大家维护的是别人写的纯代码,想修改UI就要读大量的UI代码,理解别人的思路,理清各个View的层次关系之后才能下手修改,很消耗时间与精力。如果UI复杂,且代码写得很烂,所有frame都是“写死”的数字,并且各个控件的位置都是互相关联的,“牵一发而动全身”,那基本上就是掉进坑里了,有些读者肯定体会过其中的痛苦。如果维护的是用IB开发的UI,那么修改起来就方便多了。不用读代码,不需要理解别人的思路,就能对各个View的层次关系一目了然,修改起来也会快很多,但是前提是要对IB熟悉,对Auto Layout熟悉,毕竟给控件添加约束时每个人会有自己的思路。

个人认为,IB开发与纯代码开发相比,效率至少提高两倍。1.2.2 减少大量的UI代码和“胶水代码”

由于IB是可视化的,每一步操作都相当于在写代码。以Label为例,如果用代码去实现一个UI效果,通常会写以下代码。

let tit leLabel=UILabel.init(f rame:CGRect(x:0,y:0,width:100,height:30))

tit leLabel.font=UIFont.systemFont(ofSize:12)

tit leLabel.textColor=UIColor.red

tit leLabel.textAl ignment=NSTextAlignment.center

tit leLabel.text="hel lo wor ld"

sel f.view.addSubview(tit leLabel)

如果Label展示的文字是固定的,那么用IB的话,上面的这些代码都不用写;如果label展示的文字是不固定的,那么只要写一行设置text的代码就够了,其他代码要做的事情都可以在IB中设置,而这个设置过程就像在用带有GUI的普通程序一样简单。如果将Label换成是Button,那么省下的代码量更为可观,因为Button可以针对不同的状态设置不同的属性值。

如果场景复杂,那么可能还会写更多的设置代码,例如Label的多行显示、自适应内容大小等,而这些都可以用IB来解决,不用写代码。越复杂的控件,属性越多,使用IB开发省下来的代码就越多。一个复杂的页面,省下几百行UI代码是很轻松的事情。

其实,在开发中有好多代码是“胶水代码”——不得不写,但是实际意义不大。例如页面的跳转,总是千篇一律地写着push、pop、present、dism iss,而sb中的segue可以轻松解决这些“胶水代码”,segue是sb很出色的一个功能,页面跳转可以传参,还能实现动态跳转,并且能实现一些意想不到的功能。

个人认为,IB开发与纯代码开发相比,代码量至少减少三分之一。1.2.3 适配变得十分简单

起初iPhone只有一个屏幕尺寸,iOS开发人员都不用考虑适配的问题,甚至直接把UI代码“写死”,工作之余还嘲笑一下Android的开发人员,因为Android的适配很琐碎,但是随着iPhone有了四个屏幕尺寸后,再嘲笑Android的开发人员则有点力不从心了,适配也变成了iOS中很琐碎的一件事情。Auto Layout是解决适配很好的方案,甚至是最好的方案,尤其是对复杂的、动态的UI来说,但用代码设置Auto Layout却是一件十分烦琐的事情,利用系统原生API的话会产生巨量的“胶水代码”,利用VFL(Visual Format Language)或masonry等开源库,虽然能减少一点“胶水代码”,但是有一定的学习成本,而在IB中使用Auto Layout,是一件十分简单、高效的事情,但是学习在IB中使用Auto Layout也是有成本的,并且学习的过程中会遇到很多困难。一旦我们学会之后,在IB中设置Auto Layout的效率是非常高的,可以想象点击一下鼠标和写一个名字长、参数多的方法之间的差距,代码设置Auto Layout的效率与IB相比,根本不在一个量级上。IB+Auto Layout是做适配最高效、优雅的解决方案。除此之外,利用TraitVariations做一些复杂的适配更能体现出IB的巨大优势,在做适配这方面,代码面对IB,只能望其项背。

个人认为,IB做适配与用纯代码做适配相比,优势十分明显。1.2.4 IB也可以做一些非UI的事情

如果对IB理解很透彻,对它的用法掌握很全面的话,那么可以做的事情远远超出了写UI的范畴,例如可以利用IB中的Object重新组织VC的业务逻辑,减少一些不必要的代码,这件事情意义还是很大的,它可以优雅地解决一些“神VC”(代码量很大、什么事情都做、结构杂乱、没有封装、没有层次化设计思想的VC)的困扰,还可以用IB中的ExternalObject把三个类联系起来,一旦一个UI事件触发,可以在三个类中响应该事件,每个类负责处理该事件与自己相关的部分,这个用法十分灵活,还可以利用sb中的Exit优雅地实现回调,这对A页面到B页面去选值,然后把值回传给A页面这种场景特别适用。另外,也可以把IB与一些设计模式结合使用,达到意想不到的效果,后面章节将做详细的讲解。1.2.5 利用IB学习控件可以达到事半功倍的效果

通过IB去学习不熟悉的控件,往往会达到事半功倍的效果。把控件添加到IB文件中,选中该控件,在右边栏的快速帮助检查器中可以看到该控件相关的文档,可以对这个控件有一个大体的认识,在属性检查器中能看到该控件的一些属性。可以修改这些属性,然后运行看效果,很多属性甚至不需要运行,在IB中就能看到效果,从而快速了解该控件这些属性的用法,整个学习过程无须写代码,十分方便和快捷。1.3 Interface Builder的缺点

事物都具有两面性,一般来说,程序员会相对客观地看待这个世界,当然对IB也不例外,了解了它的优点,更要知道它的缺点。下面分析一下IB的缺点,仅供参考。1.3.1 IB的执行效率没有纯代码高

这是一个不争的事实,用IB加载UI可以简单理解为两个过程:首先要把xib或sb文件对应的nib或storyboardc文件加载到内存中,然后利用这些数据去生成UI页面,加以显示。而纯代码只需一个过程,这个过程类似于IB加载UI的第二个过程——直接在内存中生成UI页面,加以显示。实际上,IB的加载分五个过程,后面会详细讲解。

笔者在早些年用第一代iPad运行App时发现:一个用IB写的有很多UI元素的页面,在加载的过程中会比用纯代码写的相同页面慢1s左右。不过现在这已经不是什么问题了,因为现在的硬件处理能力已经十分强大,国外某网站的测评结果显示:iPhone7的性能与2015年的MacBook Air相当,与2013年的MacBook Pro相当。除此之外,苹果每个版本对IB的优化也都是可圈可点的,所以虽然IB的执行效率没有纯代码高,但这个缺点可以忽略,除非读者对执行效率的要求已经达到了能用layer就不用view的程度。1.3.2 使用IB开发的过程中容易出现一些小问题

这是IB显而易见,且无可争议的缺点。可以把IB本身想象成一个小程序,只要是程序,就会有bug,所以IB是有一些小bug的。在执行的稳定性和兼容性上要比纯代码差一些,例如,iOS7对Auto Layout的支持很差,bug很多,经常会发现同样的IB文件。运行在iOS8、iOS9上是正常的,但是运行在iOS7上就有问题。然而,在iOS 7上运行Auto Layout的问题现在已经不算什么大问题了,因为从Xcode8开始,工程的Deployment Target最低的选项是iOS8,而且很多App的兼容策略都是兼容最新的三个iOS版本,所以很多App现在是从iOS8开始向上兼容的。

笔者在Xcode8上写了一个xib文件,将其File’sOwner指定成了一个VC,xib上按钮的回调放在了File’sOwner中,结果发现在iOS8上点击按钮时会crash,根本不走回调方法,很诡异,但是在iOS9、iOS10上运行正常,可能是由于Xcode8改变了IB文件结构引起的bug,解决方法是将回调放在xib关联的View的类中。

无论如何,用IB开发确实会遇到一些小问题,可能这些问题用代码开发就不会出现。因此建议读者如果在之前的项目中没有用到IB,而现在想用IB进行开发的话,要循序渐进,先在小范围用,因为在用IB的过程中可能会遇到一些小问题,等到有能力把这些小问题都解决,积累了一定的实践经验后,再逐步扩大使用范围,是一个不错的做法。当熟练使用IB后就会发现它有多么好了,至于以上所说的那点瑕疵也就不算什么了。

还有一些IB的问题可能不具有普遍性,或不会造成太大的影响。其实用IB开发中的绝大部分问题还是来自于自己,可能是代码写得有问题,或者是自身对IB掌握得不够好。如果在用因为这是大概率事件。确定不是自己的问题时,就把IB的这些“坑”记录下来,这是一个很好的学习习惯。1.3.3 有一定的学习成本

虽然学习IB需要一定的成本,但是相对于能够得到的收益来说,是非常值得的。它对开发UI效率的提升是惊人的,可以把省下来的时间花在值得深入研究的地方。俗话说技多不压身,如果新加入了一个重度使用IB的团队,有IB的基础也比较容易快速适应团队的开发环境。1.3.4 文件易冲突

IB文件的确十分容易被修改,而且还十分容易把IB文件错误提交,或者两人同时修改了同一个IB文件而导致文件冲突。要想避免这个问题可以从以下两个方面解决。

1.提交前仔细检查,不是自己要修改的IB文件不提交。

2.可以在修改IB文件之前锁定该文件,或者与同事协商,不要同时修改同一个IB文件,也可以把各自负责的业务模块划分为多个IB文件。

如果冲突真的产生了,就必须去解决它,后面章节会详细讲解如何解决IB文件的冲突,实际上文件冲突很好解决,完全没有想象中那么麻烦,在开发中也无须过分注意刚刚提到的两点,就笔者的经验来看,一般每个IB文件都是由一个人开发并维护的,所以在实际开发中IB文件冲突的事情很少发生。1.3.5 没有代码表达清晰

如果你习惯看纯代码,对IB不熟悉,那么很容易觉得还是代码表达清晰,而IB的“连线”和约束会让你一脸茫然。但如果你对IB很熟悉,就会感觉IB看上去很直观,毕竟是可视化的,找起页面来比搜代码更快捷、直观,尤其对于自己维护别人写的不熟悉的工程来说更是这样。IB的表达效率也要比代码高得多,但是不可回避的是,IB文件中的细节还是很多的,看IB文件要仔细,尤其是一些“连线”的关系和一些细节的设置。对于一个复杂的、使用了Auto Layout的页面,要想弄明白其中的约束也是很费时间和精力的事情,但是这比理解别人的代码强很多。关于这一点,仁者见仁,智者见智。1.3.6 不利于代码的封装和工程架构的组织

笔者猜测,有这种想法的程序员一般都是以下两种情况。

1.不知道IB也是可以做封装的。大家完全可以将父类定义的@IBOutlet属性和@IBAction方法与子类进行“连线”,而且可以与多个子类进行连线,这样可以用父类控制统一的逻辑,而子类则利用IB完成不同的UI布局,这是IB利于封装很明显的优势,只是在实际开发中很少被使用罢了。其实封装和IB之间的关联性很弱,用IB可能会影响工程架构的组织,但影响并没有很强的倾向性,如一定是坏的,或是好的。即使有倾向性,也更倾向于对IB有利的一面,因为Xcode的模板都是基于IB的,所以工程架构的组织上肯定是方便于IB的。

2.不知道用了IB之后有些封装就变得没有意义了。因为用纯代码封装成本很高,而用IB“简单粗暴”地开发UI成本很低。1.4 Interface Builder学习的特点

了解IB学习的特点可以使大家有的放矢,学习得更快速、高效。1.4.1 简单、容易入门

IB学习很简单,入门成本很低,毕竟它是可视化的,在操作上和学习其他软件差不多。不需要和代码结合的部分,没有编程经验和编程思想的人也都能轻易学会,但是不要因此藐视IB,因为它远比想象的要强大。对于任何技术的学习,最好都保持谦卑的态度,这样学到手的东西更多。1.4.2 容易犯错误

虽然IB学习简单,但是要和代码结合时,还是很容易犯错误的。尤其是对IB理解不深刻的人,在“连线”和“关联”上很容易犯错误,而且不容易察觉。这里要先给大家打一个“预防针”,不要因为容易犯错误就轻言放弃,坚持到最后你会发现,犯的错误都是积累的宝贵财富。1.4.3 有很多“坑”,需要积累属于自己的经验

IB学习很像英语学习,只要努力人人都能学会,但是它是一个长期积累的过程,你只有踩过的“坑”多了,积累了大量的经验,才会令IB开发过程变得更高效和轻松。读者可以在学习IB的时候坚持记笔记,记录自己对IB的理解,记录自己犯过的错,踩过的“坑”,遇到的bug,就像上学时大家记英语笔记一样,以达到快速积累、少走弯路、事半功倍的效果。1.5 Interface Builder的发展

从Xcode4.0开始,苹果把IB放在了Xcode中,当时只有xib这一种类型的文件。从Xcode 4.2开始,IB中多了sb这种类型的文件。从Xcode4.5开始,IB中引入了Auto layout布局。从Xcode5开始,sb成为新建项目的默认配置。从Xcode6.0.1开始,LaunchScreen.storyboard成为了新建项目的默认配置……

从发展上来看,苹果越来越重视IB,用IB开发UI效率的大幅提升是最大的优势,而且从单一屏幕尺寸到多种屏幕尺寸适配的工作变得越来越繁重了,同时苹果本身UI的布局系统又是相对复杂的,所以如何让开发者快速开发UI,把精力放在业务和用户体验上,是苹果要解决的很重要的问题。显然,苹果给出的答案是IB+Auto layout。所以可以看出IB是趋势所在,是发展方向,是iOS开发中应该掌握的重要技能。1.6 拓展学习:CocoaPods

在上面的学习中多次提到了CocoaPods,CocoaPods对于iOS开发来说还是比较重要的,而且在后面的学习中还会用到它,所以在这里先简单来学习一下。CocoaPods涉及的内容很多,并不是本书讨论的重点,所以这里只挑一些基础和重要的东西讲解,由于篇幅所限,可能会导致读者在学习过程中产生一些疑问,有兴趣的读者可以自行深入学习,不感兴趣的读者可以忽略这部分内容。1.6.1 CocoaPods介绍

通常在开发一个App时,会用到很多开源库和第三方库,例如AFNetworking、SDWebImage、ShareSDK、Fabric等,引入这些库通常都要配置一些环境变量或引入一些系统的.framework .dylib等,操作起来非常烦琐,而且引入的过程容易出现一些链接错误。CocoaPods则可以方便地解决这些问题,它是为iOS开发提供依赖管理的工具,也是iOS开发中使用最广泛的依赖管理工具,当然iOS8以上的工程也可以用一个去中心化的依赖管理工具——Carthage,但Carthage并非主流,有兴趣的读者可以研究一下。下面我们简单介绍一下CocoaPods。

CocoaPods是GitHub上的一个开源项目,CocoaPods的原理是将所有的依赖库放到一个Pods的工程中,然后让主工程依赖于Pods工程。Pods工程会以libPods-xxx.a(xxx为工程名)的形式被主工程使用。CocoaPods需要打开Term inal(Mac电脑自带的终端),用命令行进行安装,具体安装步骤在此不再介绍,网上有很多安装和使用教程,读者可以自行搜索并安装。

在Term inal中cd到工程文件(xxx.xcodeproj)所在目录,然后执行pod init命令,此时用ls命令查看当前文件夹,会发现多了一个Podfile文件,该文件很重要,用这个文件指定所依赖的库。打开Podfile文件,在Target'xxx'do和end之间添加要依赖的库。

//方式1

pod'AFNetworking'

//方式2

//pod'AFNetworking','~>2.5.3'

//方式3

//pod'AFNetworking','2.5.3'

读者可以用这3种方式中的任意一种来指定AFNetworking库的依赖。

•方式1会依赖最新的AFNetworking版本;

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载