iOS快速理解iOS中的MVC架构模式

来源:互联网 发布:科比常规赛数据统计 编辑:程序博客网 时间:2024/06/05 20:29

对于MVC,个人更喜欢叫做架构模式,因为MVC和我们在进行iOS开发使用的代理、单例等设计模式是有很大的区别的。

近日看到一些使用MVC架构模式的代码,发现一些同学可能不是很理解MVC架构模式,因为有很多人很可能认为自己使用了MVC架构,但是仅仅是一种表象而已。例如近日接管代码时,看到以往的同学在写代码时,虽然设置了model、view和controller,但是model中仅仅定义了几个属性而无其他操作,view中只是定义了几个子控件也没有其他的操作,大部分以及全部的数据处理逻辑和业务逻辑等都还是放在controller中,显而易见,这不是规范的MVC架构模式。

正常的MVC架构模式:

模型对象:包含了需要使用的数据,以及处理这些数据的业务逻辑和运算方式。

视图对象:展示模型对象数据的视图,只做可视效果上的更改和展示。

控制器对象:因为模型对象和视图对象是相互独立的,所以需要使用控制器对象来充当模型对象和视图对象之间的媒介。


以上说的比较简洁,通过代码直观得来讲解一下:首先我写了一个根据内容动态计算单元格高度的界面。


效果展示:



工程目录:



下面是我的controller中的内容(其中附带讲解):

#import "ViewController.h"#import "TableViewCell.h"#import "DataModel.h"static NSString *iden = @"唯一标识";@interface ViewController ()<UITableViewDataSource, UITableViewDelegate>/** 存放数据的数组 */@property (nonatomic, strong) NSMutableArray *dataArray;@end@implementation ViewController#pragma mark - 懒加载-(NSMutableArray *)dataArray{    if (_dataArray == nil){        //加载本地的数据        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"source.plist" ofType:nil];        NSArray *array = [NSArray arrayWithContentsOfFile:filePath];        _dataArray = [NSMutableArray array];        for (NSDictionary *dic in array) {            DataModel *model = [DataModel configDataModelWithDictionary:dic];            [_dataArray addObject:model];        }    }    return _dataArray;}#pragma mark - 控制器声明周期- (void)viewDidLoad {    [super viewDidLoad];        UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];    tableView.dataSource = self;    tableView.delegate = self;    tableView.separatorColor = [UIColor clearColor];    [self.view addSubview:tableView];}#pragma mark - UITableViewDataSource- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{    return self.dataArray.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:iden];    if (cell == nil){        cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:iden];    }    /**     将model的数据传递给cell,其中包含 1>需要展示的文本内容 2>cell中子控件的frame数据     */    cell.model = self.dataArray[indexPath.row];    return cell;}#pragma mark - UITableViewDelegate- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{    /**     单元格的高度属于数据,应包含在model中的,所以在返回高度的代理方法中,直接返回model中的高度数据     在model中进行高度计算的时候,我们同时进行其他的数据计算(例如名言警句的标签的高度的计算)     */    DataModel *dataModel = self.dataArray[indexPath.row];    return dataModel.cellHeight;}@end


model中的代码:

DataModel.h:

#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>@interface DataModel : NSObject//根据数据源建立model+ (instancetype) configDataModelWithDictionary:(NSDictionary *)dictionary;/** 单元格的高度 */@property (nonatomic, assign) CGFloat cellHeight;/** 电影名字 */@property (nonatomic, strong) NSString *name;/** 精选的句子 */@property (nonatomic, strong) NSString *content;/** 电影名字标签的frame */@property (nonatomic, assign) CGRect nameLabelFrame;/** 精选句子的便签的frame */@property (nonatomic, assign) CGRect contentLabelFrame;@end
DataModel.m:

#import "DataModel.h"#define KWidth  [UIScreen mainScreen].bounds.size.width#define KHeight [UIScreen mainScreen].bounds.size.height#define space  20@implementation DataModel+ (instancetype) configDataModelWithDictionary:(NSDictionary *)dictionary{    DataModel *model = [[self alloc] init];    model.name = dictionary[@"name"];    model.content = dictionary[@"text"];    return model;}- (CGFloat)cellHeight{    if (_cellHeight == 0){        //名字标签的frame        _nameLabelFrame = CGRectMake(space, space, KWidth-space*2, space*2);                //句子标签的frame        //根据内容动态设置高度        CGSize contentLabelMaxSize = CGSizeMake(KWidth-space*2,MAXFLOAT);        // 计算文字的高度        CGFloat contentLabelHeight = [self.content boundingRectWithSize:contentLabelMaxSize                                                   options:NSStringDrawingUsesLineFragmentOrigin                                                attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:20]}                                                   context:nil].size.height;        _contentLabelFrame = CGRectMake(space, space*4, KWidth-space*2, contentLabelHeight);                //单元格的高度        _cellHeight = space*5+contentLabelHeight;    }    return _cellHeight;}@end


View中的代码:

TableViewCell.h:

#import <UIKit/UIKit.h>@class DataModel;@interface TableViewCell : UITableViewCell/** 模型数据 */@property (nonatomic, strong) DataModel *model;@end
TableViewCell.m:

#import "TableViewCell.h"#import "DataModel.h"@interface TableViewCell ()/** 电影名称标签 */@property (nonatomic, strong) UILabel *nameLabel;/** 精选的句子标签 */@property (nonatomic, strong) UILabel *contentLabel;/** 分割线 */@property (nonatomic, strong) UIView *operationView;@end@implementation TableViewCell//初始化方法中添加需要的子控件- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {        /** 电影名称标签 */        self.nameLabel = [[UILabel alloc] init];        self.nameLabel.font = [UIFont systemFontOfSize:17];        self.nameLabel.backgroundColor = [UIColor lightGrayColor];        [self.contentView addSubview:self.nameLabel];                /** 精选的句子标签 */        self.contentLabel = [[UILabel alloc] init];        self.contentLabel.font = [UIFont systemFontOfSize:20];        self.contentLabel.backgroundColor = [UIColor brownColor];        self.contentLabel.numberOfLines = 0;        [self.contentView addSubview:self.contentLabel];                //添加分割线        self.operationView = [[UIView alloc] init];        self.operationView.backgroundColor = [UIColor blackColor];        self.operationView.alpha = 0.8;        [self.contentView addSubview:self.operationView];                //取消点击的效果        self.selectionStyle = UITableViewCellSelectionStyleNone;    }    return self;}//布局子控件的时候设置子控件的frame- (void)layoutSubviews{    _nameLabel.frame = self.model.nameLabelFrame;    _contentLabel.frame = self.model.contentLabelFrame;    _operationView.frame = CGRectMake(0, CGRectGetHeight(self.contentView.frame)-1, [UIScreen mainScreen].bounds.size.width, 1);}//cell的model的setter方法,进行数据的赋值- (void)setModel:(DataModel *)model{    _model = model;    _nameLabel.text = model.name;    _contentLabel.text = model.content;}@end

代码下载地址:http://download.csdn.net/detail/wuzesong/9697013








1 0