转载

手把手教学:详解Swift中的iOS设计模式

说到设计模式,相信大家都不陌生,但是又有多少人知道它背后的真正含义?绝大多数程序员都知道设计模式十分重要,不过关于这个话题的文章却不是很多,开发者们在开发的时候有时也不太在意设计模式方面的内容。

设计模式针对软件设计中的常见问题,提供了一些可复用的解决方案,开发者可以通过这些模板写出易于理解且能够复用的代码。正确的使用设计模式可以降低代码之间的耦合度,从而很轻松的修改或者替换以前的代码。

如果你对设计模式还很陌生,那么告诉你一个好消息!在iOS的开发过程中,其实你不知不觉已经用了很多设计模式。这得益于Cocoa提供的框架和一些良好的编程习惯。接下来的这篇教程将会带你一起飞,去领略设计模式的魅力。

我们将会完成一个完整的应用,展示音乐专辑和专辑的相关信息。 通过这个应用,我们会接触一些Cocoa中常见的设计模式:

  • 创建型(Creational):单例模式(Singleton)
  • 结构型(Structural):MVC、装饰者模式 (Decorator)、适配器模式(Adapter)、外观模式 (Facade)
  • 行为型(Behavioral):观察者模式(Observer)、备忘录模式(Memento)

这篇文章不是什么长篇大论的理论知识,你会在开发应用的过程中慢慢学会这些设计模式。

先来预览一下最终的结果:

手把手教学:详解Swift中的iOS设计模式

看起来还是不错的,开始学习接下来的内容吧。勇敢的少年们,快来创造奇迹!

开始

下载 初始项目 并解压,在Xcode中打开BlueLibrarySwift.xcodeproj项目文件。

项目中有三个地方需要注意一下:

  1. ViewController有两个IBOutlet ,分别连接到了UITableView 和UIToolBar上。
  2. 在StoryBoard上有三个组件设置了约束。最上面的是专辑的封面,封面下面是列举了相关专辑的列表,最下面是有两个按钮的工具栏,一个用来撤销操作,另一个用来删除你选中的专辑。
  3. 一个简单的HTTP客户端类(HTTPClient),里面还没有什么内容,需要你去完善。

手把手教学:详解Swift中的iOS设计模式

【注意】其实当你创建一个新的Xcode的项目的时候,你的代码里就已经有很多设计模式的影子了: MVC、委托、代理、单例 - 真是众里寻他千百度,得来全不费功夫。

在学习第一个设计模式之前,你需要创建两个类,用来存储和展示专辑数据。

创建一个新的类,继承NSObject名为Album,记得选择Swift作为编程语言然后点击下一步。

打开Album.swift然后添加如下定义:

var title : String! var artist : String! var genre : String! var coverUrl : String! var year : String!

这里创建了五个属性,分别对应专辑的标题、作者、流派、封面地址和出版年份。

接下来我们添加一个初始化方法:

init(title: String, artist: String, genre: String, coverUrl: String, year: String) {   super.init()   self.title = title   self.artist = artist   self.genre = genre   self.coverUrl = coverUrl   self.year = year }

这样我们就可以愉快地初始化了。

然后再加上下面这个方法:

func description() -> String {   return "title: /(title)" +    "artist: /(artist)" +    "genre: /(genre)" +    "coverUrl: /(coverUrl)" +    "year: /(year)" }

这是专辑对象的描述方法,详细的打印了 Album 的所有属性值,方便我们查看变量各个属性的值。

接下来,再创建一个继承自 UIView 的视图类 AlbumView.swift。

在新建的类中添加两个属性:

private let coverImage: UIImageView!  private let indicator: UIActivityIndicatorView!

coverImage代表了封面的图片,indicator则是在加载过程中显示的等待指示器。

这两个属性都是私有属性,因为除了AlbumView之外,其他类没有必要知道他俩的存在。在写一些框架或者类库的时候,这种规范十分重要,可以避免一些误操作。

接下来给这个类添加初始化化方法:

required init(coder aDecoder: NSCoder) {    super.init(coder: aDecoder) } init(frame: CGRect, albumCover: String) {  super.init(frame: frame)  backgroundColor = UIColor.blackColor()  coverImage = UIImageView(frame: CGRectMake(5, 5, frame.size.width - 10, frame.size.height - 10))  addSubview(coverImage)  indicator = UIActivityIndicatorView()  indicator.center = center  indicator.activityIndicatorViewStyle = .WhiteLarge  indicator.startAnimating()  addSubview(indicator) } 

因为UIView遵从NSCoding协议,所以我们需要NSCoder的初始化方法。不过目前我们没有encode和decode的必要,所以就把它放在那里就行,调用父类方法初始化即可。

在真正的初始化方法里,我们设置了一些初始化的默认值。比如设置背景颜色默认为黑色,创建 ImageView 并设置了 margin 值,添加了一个加载指示器。

最终我们再加上如下方法:

func highlightAlbum(#didHighlightView: Bool) {     if didHighlightView == true {         backgroundColor = UIColor.whiteColor()     } else {         backgroundColor = UIColor.blackColor()     } }

这会切换专辑的背景颜色,如果高亮就是白色,否则就是黑色。

在继续下面的内容之前, Command + B 试一下确保没有什么问题,一切正常?那就开始第一个设计模式的学习啦!

MVC——设计模式之王

Model-View-Controller (缩写 MVC ) 是 Cocoa 框架的一部分,并且毋庸置疑是最常用的设计模式之一。它可以帮你把对象根据职责进行划分和归类。

手把手教学:详解Swift中的iOS设计模式

作为划分依据的三个基本职责是:

  • 模型层(Model):存储数据并且定义如何操作这些数据。在我们的例子中,就是Album类。
  • 视图层(View):负责模型层的可视化展示,并且负责用户的交互,一般来说都是继承自UIView这个基类。在我们的项目中就是AlbumView这个类。
  • 控制器(Controller):控制器是整个系统的掌控者,它连接了模型层和数据层,并且把数据在视图层展示出来,监听各种事件,负责数据的各种操作。不妨猜猜在我们的项目中哪个是控制器?啊哈猜对了ViewController这个类就是。

如果你的项目遵循MVC的设计模式,那么各种对象要不是Model,要不是View,要不就是Controller。当然在实际的开发中也可以灵活变化,比如结合具体业务使用MVVM结构给ViewController瘦瘦身,也是可以的。

三者之间的关系如下:

手把手教学:详解Swift中的iOS设计模式

模型层通知控制器层任何数据的变化,然后控制器层会刷新视图层中的数据。视图层可以通知控制器层用户的交互事件,然后控制器会处理各种事件以及刷新数据。

你可能会感觉奇怪:为什么要把这三个东西分开来,而不能揉在一个类里呢?那样似乎更简单一点嘛。

之所以这样做,是为了将代码更好的分离和重用。理想状态下,视图层应当和模型层完全分离。如果视图层不依赖任何模型层的具体实现,那么就可以很容易的被其他模型复用,用来展示不同的数据。

举个例子,比如在未来我们需要添加电影或者什么书籍,我们依旧可以使用 AlbumView 这个类作为展示。更久远点来说,在以后如果你创建了一个新的项目并且需要用到和专辑相关的内容,你可以直接复用 Album 类因为它并不依赖于任何视图模块。这就是 MVC 的强大之处,三大元素,各司其职,减少依赖。

如何使用MVC模式

首先,你需要确定你的项目中的每个类都是三大基本类型中的一种:控制器、模型、视图。不要在一个类里糅合多个角色。目前我们创建了Album类和AlbumView类是符合要求的,做得很好。

然后,为了确保你遵循这种模式,你最好创建三个项目分组来存放代码,分别是Model、View、Controller,保持每个类型的文件分别独立。

接下来把Album.swift拖到Model分组,把AlbumView.swift拖到View分组,然后把ViewController.swift 拖到Controller分组中。

现在你的项目应该是这个样子:

手把手教学:详解Swift中的iOS设计模式

现在你的项目已经有点样子了,不再是各个文件颠沛流离居无定所了。显然你还会有其他分组和类,但是应用的核心就在这三个类里。

现在你的内容已经组织好了,接下来要做的就是获取专辑的数据。你将会创建一个 API 类来管理数据 - 这里我们会用到下一个设计模式:单例模式。

单例模式

单例模式确保每个指定的类只存在一个实例对象,并且可以全局访问那个实例。一般情况下会使用延时加载的策略,只在第一次需要使用的时候初始化。

【注意】在iOS中单例模式很常见,NSUserDefaults.standardUserDefaults()、UIApplication.sharedApplication()、UIScreen.mainScreen()、NSFileManager.defaultManager()这些都是单例模式。

你可能会疑惑了:如果多于一个实例又会怎么样呢?代码和内存还没精贵到这个地步吧?

某些场景下,保持实例对象仅有一份是很有意义的。举个例子,你的应用实例(UIApplication),应该只有一个吧,显然是指你的当前应用。还有一个例子:设备的屏幕(UIScreen)实例也是这样,所以对于这些类的情况,你只想要一个实例对象。

正文到此结束
Loading...