本节书摘来自异步社区《iOS App界面设计创意与实践》一书中的快速提示:iOS开发策略,作者【美】Shawn Welch,更多章节内容可以访问云栖社区“异步社区”公众号查看
快速提示:iOS开发策略
iOS App界面设计创意与实践
在我们深入iOS UI、动画和手势背后的技术之前,掌握一些基础知识很重要。对于设计师而言,虽然不要求读完本书后能够编写代码,但是有一些标准的iOS开发策略,开发者或者必须在基于iOS SDK开发中遵循,或者应该作为最佳实践来遵循。作为设计师,了解这些因素对开发人员的影响,对于理解如何设计最佳用户体验是至关重要的。作为开发人员,快速温习一下最佳实践并没有害处。
模型—视图—控制器
当谈及编码原则时,模型—视图—控制器(MVC)是最基础的。其核心思想是,MVC描述了应用程序的数据、用户界面和“大脑”的关系。通过设计,MVC的三个组成部分都保持独立。在图1.7中,你可以看到模型—视图—控制器体系结构的基本关系。其中,黑线表示直接关联,而浅色线表示间接关联。
模型—视图—控制器设计对于iOS应用程序尤其重要。为了有助于解释原因,让我们使用iPhone的地址簿应用程序作为例子。
模型
MVC中的模型是应用程序存储数据的地方。对于地址簿来说,数据是所有的联系人。该模型知道地址簿里每个人的所有数据,但是它没有办法把数据呈现给用户看。
因为地址簿的模型是与视图和控制器分开的,作为开发人员,你可以在自己的应用程序中访问用户地址簿联系信息,并且用于不同的用途。你可以重新设计联系信息呈现给用户的方式,或者重新设计你的应用程序与数据的交互方式。同样,当设计自己的应用程序时,把模型与视图和控制器分开的设计能让升级、修正bug和重用代码更加轻松和快速。
视图
MVC中的视图通常是用户界面:即用户所看到的,包括使用应用程序所需要的选项。在某些情况下,视图可以直接和模型对话,但是通常是通过控制器来和模型产生交互,控制器决定了一个行为该做什么。在通讯簿的例子中,视图是你在设备屏幕上看到的联系人名单。当你在视图中选择一个联系人时,这个行为会发送到控制器。然后控制器从模型中取得必要的联系信息,再把这些信息往回传递给视图,视图最终显示给用户。
控制器
控制器是应用程序的大脑。控制器通常决定了应用程序的导航风格和工作流程。模型存储数据,视图呈现数据,而控制器决定了如何存储和存储什么样的数据,以及如何呈现和呈现什么样的数据。
让我们再来看通讯簿的例子,但是这次来搜索一个联系人。我们在视图的搜索框里轻敲,开始执行搜索,视图告知控制器“我在搜索联系人XYZ”控制器接受这个搜索请求,然后决定如何以最优的方式从模型那里获取所需的信息。一旦控制器从模型那里获得所需的信息,它就传回给视图,最后视图把信息呈现给用户。
值得注意的是,MVC架构内部是循环的。信息和行为在组件之间自由流动,但是需要良好地建立每个组件,以便这些核心任务能独立。
获取代码
从 fromideatoapp.com/downloads/ch1#mvc 下载演示模型—视图—控制器的演示程序,然后自己试一试。
子类
子类化是iOS开发的另一个核心原则,并且是面向对象编程的基本概念。子类化是基于继承的,这意味着子类继承超类或者父类的属性。这听起来非常技术化和混乱,但它实际上并不是。让我们来看一个子类化的例子,它与编程没有任何关系。
想象一下你要买一辆新车。当你走进一家经销商,第一眼就看到一辆普通的四门轿车。销售员告诉你,这辆汽车配备了基本的功能,它有红色、蓝色或银色可以选择。这款车听起来挺划算的,但你告诉销售员你想要的是黑色,并且需要配备内置卫星无线电导航系统,这时优秀的销售员一般都会把你领到下一辆车跟前:SE车型,价格较高,但是它是黑色的,并且除了最基本的配置之外,还有一个内置卫星无线电导航系统。
这个例子中,你可以认为SE车型是标准车型的一个子类。
当一个东西是子类时,意味着在默认情况下,子类包含父类所有的属性和功能。但是,子类可以在超类基础上重写或者添加新的属性(不改变超类的功能)。在我们的汽车比喻中,默认情况下,SE车型拥有标准款车型所提供的一切。但除了这些功能之外,你可以改变汽车的颜色为黑色,并添加新的属性,例如内置卫星无线电导航系统。
你将会发现,iOS在整个SDK中使用的标准用户界面元素和控制器原理和前面一样。通常情况下,你可以利用这些标准元素,继承它们从而改造它们,使其符合你的独特需求。我们将在第二篇中更加详细地探讨子类化。
内存管理
正如前面我们在讨论Instruments时提到的,开发人员负责创建和释放内存变量。这对开发新手来说很棘手,那么我们所说的“创建”和“释放“变量到底是什么意思呢?当你创建一个变量时,你的应用程序会分配少量的内存来存储该变量的值。当你用完了一个变量时,该内存空间需要被释放(用于以后再次被新的变量使用)。如果一个变量使用的内存块没有释放,它会导致内存泄漏,这意味着有一个不被任何代码使用或引用的变量占用着内存空间。当内存泄漏得越来越多时,你的应用程序变得不稳定并且响应速度慢。这是因为移动设备上的宝贵资源——内存正在被永远不再使用的变量浪费着。
iOS应用程序是使用Objective-C编程语言来编写的,这种语言使用保留—释放方法来管理内存。所用的概念很简单:每个变量有一个保留计数,这个保留计数由对变量的引用的数量决定。当一个变量的保留计数为0时,iOS就会在某个时间自动把它从内存中释放。
因此,与其我们自己试图从内存中删除一个变量,还不如当我们用完变量后通过release方法减少其保留计数,如果保留计数是0,iOS就会自动删除这个变量。请看下面的代码块:
1 UIViewController *myVariable = [[UIViewController alloc]
initWithNibName:nil bundle:nil];
2 myVariable.title = @"My Application";
3 [self.navigationController
pushViewController:myVariable animated:YES];
4 [myVariable release];
第1行中,我们在内存里创建了一个名为myVariable的变量。一旦创建完成,myVariable的保留计数就是1。第2行设置了myVariable的title属性。设置变量的title或操纵其他属性不会影响保留计数,所以在第2行的末尾,myVariable保留计数仍然是1。然而,在第3行,我们把一个控制器压入到一个导航控制器。当我们把myVariable压入到一个导航控制器栈中,导航控制器栈要确保当需要变量时变量必须存在,因此它会递增保留计数。
第3行后,myVariable的保留计数是2。因为我们不再需要这个变量,并把维护变量的责任移交给导航控制器(它递增了保留计数),在第4行我们在myVariable上调用了release方法,这会递减保留计数。所以,在第4行后,myVariable的保留计数是1。
当导航控制器不再需要引用myVariable时,它会自动为myVarible调用release方法。由于myVariable保留计数是1,当导航控制器调用release方法时,结果是保留计数变成0,然后变量自动从内存中释放(删除)。如果没有在第4行调用release方法,将导致产生一个内存泄漏,因为myVariable的保留计数永远不会变成0。
此外,如果在我们的代码块中调用两次release方法,将导致保留计数变成0,然而导航控制器仍然可以访问这个变量,当导航控制器下一次试图引用myVariable变量(现在已经不存在了)时,应用程序将会崩溃。