原文地址:http://www.raywenderlich.com/86477/introducing-ios-design-patterns-in-swift-part-1
Update 04/22/2015: Updated for Xcode 6.3 and Swift 1.2.
Update note: This tutorial was updated for iOS 8 and Swift by Vincent Ngo. Original Post by Tutorial team member Eli Ganem.
*************原文只有swift版本,我顺便添加OC版本,因为不了解swift,所以我写的OC代码可能会有错,请见谅************
设计模式是在软件设计中对常见问题的复用解决方案,是帮助你写出便于理解与复用的代码的模板,也帮助你写出低耦合代码以便较为轻松地变更代码内容。
在这篇分为两个部分的教程中,你会创建一个Music Library app(音乐库应用),这个应用会展示音乐专辑和相关信息。
在开发这个app的过程中,你会熟悉最常用的Cocoa设计模式:
- Creational(创建型): Singleton(单例模式)
- Structural(结构型): MVC, Decorator(装饰模式), Adapter(适配器模式), Facade(外观模式).
- Behavioral(行为型): Observer(观察者模式),Memento(备忘录模式)
不要误以为这篇文章是走理论的;你在这个app中会用到大部分上面的设计模式,你的app最后会是这样:
下载starter project,解压,在Xcode中打开BlueLibrarySwift.xcodeproj
此项目有三个重点:
1. 有两个IBOutlet连接到ViewController,一个是table view,一个是toolbar
2. storyboard有三个部分,已经为AutoLayout创建了约束,顶部部分是展示专辑封面的地方;封面下的部分是table view,展示专辑相关信息;最后一个部分是toolbar,有两个button,从图上可以看到:一个undo,一个删除。
3. 一个HTTP Client类(HTTPClient),类的实现由你稍后来编写。
Note:你知道当你创建一个新的Xcode项目时,你的代码就已经带有设计模式了吗?MVC,Delegate,Protocol,Singleton - 你直接得到了
在深入第一种设计模式前,需要先创建两个类分别存储,展示数据
- 新建:File\New\File…(或者按快捷键 Command+N).选择 iOS > Cocoa Touch Class ,点击Next. 类名写为Album,
NSObject的子类
. 最后:选择语言为Swift,点击Next,Create. - 打开Album.swift,添加下列属性。
1 // swift 2 3 var title : String! 4 var artist : String! 5 var genre : String! 6 var coverUrl : String! 7 var year : String! 8 9 // Objective-C 10 11 @property (nonatomic,copy) NSString *title; 12 @property (nonatomic,copy) NSString *artist; 13 @property (nonatomic,copy) NSString *genre; 14 @property (nonatomic,copy) NSString *coverUrl; 15 @property (nonatomic,copy) NSString *year;
创建了5个属性,Album类将会实时关注这5个属性。
- 接下来添加Album对象初始化方法
// Swift 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 } // Objective-C // Album.h +(Album *)initWithTitle:(NSString *) title artist:(NSString *)artist genre: (NSString *)genre coverUrl:(NSString *)coverUrl year:(NSString *)year; // Album.m +(Album *)initWithTitle:(NSString *) title artist:(NSString *)artist genre: (NSString *)genre coverUrl:(NSString *)coverUrl year:(NSString *)year{ if(self = [super init]){ self.title = title self.artist = artist self.genre = genre self.coverUrl = coverUrl self.year = year } }
- 重写description方法
// Swift override var description: String { return "title: \(title)" + "artist: \(artist)" + "genre: \(genre)" + "coverUrl: \(coverUrl)" + "year: \(year)" } // Objective-C (NSString *)description{ return [NSString stringWithFormat:@"title:%@,artist:%@,genre:%@,coverUrl:%@,year:%@",self.title,self.artist,self.genre,self.coverUrl,self.year]; }
description方法以字符串形式返回Album对象的属性。
- 建立第二个类,把类名设定为AlbumView,继承自UIView
1 // Swift 2 3 private var coverImage: UIImageView! 4 private var indicator: UIActivityIndicatorView! 5 6 // Objective-C 7 // 写到.m文件里 8 9 @implementatin AlbumView 10 11 @property (nonatomic,weak) UIImageView *coverImage; 12 @property (nonatomic,weak) UIActivityIndicatorView *indicator; 13 14 @end
coverImage是专辑封面图片,第二个属性是实时跟踪封面加载情况的活动指示器
这两个属性设定为私有类型是因为在AlbumView类之外的地方不需要知道这两个属性的存在,它们只是用在内部实现功能里。当你要创建一个供大家使用的库或者框架时使用这个非常重要的规则就能保持私有变量信息不公开。
- 同样,为AlbumView类添加初始化方法
required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) commonInit() } init(frame: CGRect, albumCover: String) { super.init(frame: frame) commonInit() } func commonInit() { backgroundColor = UIColor.blackColor() coverImage = UIImageView(frame: CGRect(x: 5, y: 5, width: frame.size.width - 10, height: frame.size.height - 10)) addSubview(coverImage) indicator = UIActivityIndicatorView() indicator.center = center indicator.activityIndicatorViewStyle = .WhiteLarge indicator.startAnimating() addSubview(indicator) } // 然而已经不知道OC应该怎么写。
NSCoder需要被初始化因为UIView遵从NSCoding
commonInit是一个辅助方法,它被用到了两个init方法当中,你之后会需要这些方法,设定AlbumView的默认条件。背景黑色,为imageView设置5个像素的边缘,以及将coverImage和indicator属性添加到父视图。
- 最后:添加下列方法
// Swift func highlightAlbum(#didHighlightView: Bool) { if didHighlightView == true { backgroundColor = UIColor.whiteColor() } else { backgroundColor = UIColor.blackColor() } } //OC - (void) highlightAlbum:(BOOL)didHighlightView{ if([self didHighlightView]){ self.view.coverImage.backgroundColor = [UIColor whiteColor]; }else{ self.view.coverImage.backgroundColor = [UIColor blackColor]; } }
高亮时专辑封面为白色,反之为黑色。
编译工程,确保一切都没有问题,然后准备开始第一个设计模式的学习。
MVC – The King of Design Patterns 设计模式王者
MVC是Cocoa的基石,毫无疑问它是被运用最多的设计模式。它按照对象的常规角色对对象进行分类,且鼓励开发者这样为代码创建目录以保证项目层次清晰明确。
这三种角色分别是:
- Model(模型):Model对象存储应用数据,定义管理这些数据的方法,就像在这个项目中你的Album类。
- View(视图):View对象负责把Model和与用户的交互借口视觉呈现出来,基本上就是所有的UIView衍生出的对象,就像这个项目中你的AlbumViw类。
- Controller(控制器):Controller对象是协调以上工作的媒介,它拿到Model的数据然后在View中将之呈现出来,还有监听交互情况并按照它管理数据,现在你知道你的项目中的Controller是谁了吗?没错,就是ViewController。
要想实现好这个设计模式,就要把每个对象都分配到Model,View,Controller组中。
下图可以描述MVC的关系:
当Model对象的数据发生改变时,它会通知Controller对象,然后Controller对象更新对应的View对象上展示的数据。当用户在View对象进行了交互操作时,View对象会通知Controller对象,然后Controller对象会更新对应的Model对象中的数据。
未完待续 第一次更新:2016-03-02 11:58:18