参考:
MVC 设计模式
MVC 是一种设计模式。我们创建的对象根据其职责来划分,它要么属于 M:Model
,要么属于 V:View
,要么属于C:Controller
,下面我们分别简要介绍一下 Model、View、ViewController。
Model
Model 一般是我们对真实世界中一些事物的抽象,来定义的一些数据对象,它包含我们所需要的数据以及对这些数据的操作。
Model 一般是负责定义及存储数据,是与用户界面上用于显示的各个视觉元素是无关的。
View
接下来是 View,在 iOS 中,View 一般是 UIKit 中 UIView 及其子类的一些实例,是用户可以看得见的对象。比如说 UIView,是用于界面元素展示的类的基类,以及 UIButton、UILabel、UISlider、UITextField 等等。
ViewController
Objective-C 一般是 ViewController
一般是 UIViewController
及其子类的实例,系统提供给我们的比较常用的 ViewController
有以下的这些:
UIViewController
:用来展示多个视图控制器;UITabBarController
:在UIViewController
的特性之上,加入可以在这些控制器之间进行切换;UINavigationController
:在UIViewController
的特性之上,在视图控制器间进行导航控制;UITableViewController
:展示一个单列的表的视图控制器;UICollectionViewController
:以及展示集合视图的;UIAlertViewController
:展示弹框消息。
在项目中,ViewController 可以通过持有的方式直接与 View 与 Model 进行通信。
ViewController
的职责是什么?
视图管理:视图控制器最重要的作用是管理视图的层次结构。
每个视图控制器都有一个根视图,就是
UIViewController
的view
属性,它包含所有视图控制器的显示内容。在该根视图中,您可以添加显示内容所需的视图。视图控制器始终具有对其根视图的引用,并且根视图视图都具有对其子视图的强引用。充当 View 及 Model 的媒介:两者通过 ViewController 进行通信。
处理用户的交互:通常来说视图将用户的交互事件传递给自己的代理对象来进行事件的处理,这个代理对象通常就是 ViewController。
资源管理:视图控制器负责管理由其创建的对象。
在 UIViewController 子类中,是我们开发者负责管理显式创建的任何对象。由于移动设备的内存是有限的,当设备的可用内存不足时,UIKit 会要求应用程序释放他们不再需要的任何资源。
这样做的一种方法是调用视图控制器的
didReceiveMemoryWarning
方法:在这个方法里删除对不再需要的对象,或者稍后可以轻松地重新创建的对象的引用。例如,您可以使用该方法删除缓存的数据。在发生内存不足的情况时,尽可能多地释放内存是非常重要。消耗过多内存的应用程序可能会被系统彻底终止以恢复内存。
OC 中的内容 VC 种类
UIScrollView
这是一个比较重要的类,UITableView
, UICollectionView
, UITextView
这些视图都是继承自它。在 iOS 中,滚动视图 UIScrollView
通常用于查看大于屏幕的内容。
两个比较重要的属性:
frame
:这个属性控制了UIScrollView
的位置以及大小;可以理解为窗口的大小;ContentSize
:定义了UIScrollView
能显示的内容区域的大小;可以理解为图片的大小;
很显然,如果将 frame 的宽度或者高度设置为最大,就可以实现拖动和分页了。但是如何让它恰好停止在下一个视图呢,只需要设置下面的属性:
|
|
UITableView
UIScrollView
的子类,可以通过 initWithFrame
创建:
|
|
在创建时必须指定一个创建风格,有以下两个选项:
UITableViewStylePlain
:通讯录类似风格;UITableViewStyleGrouped
:系统设置类似风格。
UITableView
主要是以下的几个部分组成:
|
|
如何创建 UITableView
的子视图?
对于 UITableView,我们一般不通过创建子视图并添加其为 UITableView 的子视图来展示内容;
一般把这个工作交给一个遵守
UITableViewDataSource
协议的对象:1 2 3 4 5 6 7 8 9
@optional - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; // 用于指定一个 TableView 中有多少个 Section。可选方法,默认返回为 1 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; // 这个方法告诉 UITableView 第几个 section 要显示多少行内容 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; // 在指定的 indexPath 上具体的要展示的 Cell 长什么样子
PostScript:上面的第三个方法,引入了
NSIndexPath
这个类型,他用于指定一个 Cell 的位置。我们可以使用以下的类方法直接创建这个对象:1 2
+ (instancetype)indexPathForRow:(NSInteger)row inSection:(NSInteger)section; + (instancetype)indexPathForItem:(NSInteger)item inSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
UITableViewCell
上面 UITableViewDataSource
协议的第三个方法指定了 UITableViewCell
这个对象,顾名思义,他就是用来指定 cell 样式的一个类。
这个对象有一个名为 contentView
的子视图,它有三个子视图。关于这三种视图有以下的四种排列模式:
OC 中的容器 VC 种类
UINavigationController
ViewController
的栈操作包括 Pushing、Poping,其他的展现方式还包括 Presenting、Dissmissing;
注意以下的几点:
所有通过
prensent
方式展现的ViewController
都需要主动调用dismiss
;使用
push
方法展现ViewController
需要通过调用pop
方法进行消失展示;push
以及pop
方法只可以在UINavigationController
上被调用(其他的只能调用present
);当调用一个
ViewController
的dismiss
方法时,所有通过该 vcpresent
出来的 vc 都会被销毁,同时只有最顶部的ViewController
会展现动画。swift 为
UIViewController
定义了一个属性presentingViewController.dissmiss
用于执行这一操作;同时 Apple 也提供了一个 API,用于仅仅销毁当前 vc,
presentedViewController.dismiss
;
presentedViewController
与 presentingViewController
:
UIViewController
的两个属性,默认值为nil
;- 当 vcA 通过
presentViewController:animated:completion:
方法展现 vcB 时:vcB.presentingViewController
会被置为vcA
;vcA.presentedViewController
会被置为vcB
;
UITabBarController
iOS 官方 App 中“博客”、“闹钟”等的底部导航风格。