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

对于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








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值