MVC 学习

IOS 开发模式 之MVC模式

说到MVC 模式,根据意思来说 Model ,View,Controller  模型,视图,控制。

说是这么说,但是还是不明白到底应该怎么弄。(这其实是说我自己的,从下面就能看出)。


Model  模型,建立一个数据模型,里面是我们需要用到的数据,可以建立多个模型,一个模型里面包含另一个模型。

View   视图,创建视图。把需要用到的控件视图,建立一个子类。在里面设置视图,最后返回出来,代理一般在自己界面中是实现,一般就是自己创建的子类中实现。有时候还可以对model 的数据操作 

Controller 控制器。 里面就是一些逻辑的处理 ,把返回的View 视图添加到界面上,删除控件等逻辑的是实现,对Model 数据的操作。

(我目前是这样理解的,根据MVC的定义,View只需要处理视图,对数据Model 的处理 应该在Controller 中,我目前在View 处理数据,以后再根据理解慢慢更改)

下面粘贴一段 网上复制过来的其他网友的话:

在iOS cocoa touch 编程中, MVC机制被发挥得淋漓尽致。 MVC 示意图如下。 只有充分理解了MVC,才能在编写出优雅的iOS app。为充分理解 MVC, 相关的概念(比如: Delegate、 Protocol、 Notification 等)也要了然于胸。

     MVC 约定, Model 不允许与View 打交道。 Model 是管理数据的, 当Model中的数据发生变化时,与之对应的视图应更新。 这就需要一种机制来支持。为此 iOS 框架提供了两种支持机制: Notification 和KVO (Key-Value Observing)。

  KVO 可简单理解为,为你所关注的 Key 对象注册一个监听器。 当有数据发生变化时,就会发出广播给所有的监听器。

      MVC 也约定, View 不允许直接引用Modal, 它只能被Controller 所控制。 Controller 控制 View 显示什么数据。我们知道,View 所要显示的数据是来源于 Modal, View 上产生的事件 ( 比如 Touch事件)需要通知 Controller。 既然MVC 不允许直接打交道,就需要提供一种机制。 

  不错, iOS 确实提供了一种机制, 名曰: Delegate。 Delegate 这个词, 有人将它译为“委托”,也有人将它译为“代理”。名称上的差异没有什么,重要的是如何理解 Delegate。 Delegate设计模式的引入,就是为了解决UIView与Controller松耦合互动问题。

网友的链接



下面的代码 有我自己写的 还有参考其他大神的


定义的Model

SectionModel

#import <Foundation/Foundation.h>

//分区模型

@interface SectionModel : NSObject

@property (nonatomic, copy) NSString *sectionTitle;

//是否可以展开

@property (nonatomic, assign) BOOL isExpanded;

//分区下面可以有很多个cell对应的模型

@property (nonatomic, strong) NSMutableArray *cellModels;

@end


CellModel

#import <Foundation/Foundation.h>

@interface CellModel : NSObject

@property (nonatomic, copy) NSString *title;

@end


创建View

我自定义了一个TableView 并在里面对数据进行 处理,但是这样不符合MVC模式 我只是根据自己理解这样设置的

#import <UIKit/UIKit.h>

@interface TableView : UITableView

-(instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style;

@end


TableView 的实现文件 我导入了Model 模型文件

#import "TableView.h"

#import "HeaderView.h"

#import "SectionModel.h"

#import "CellModel.h"


@interface TableView ()<UITableViewDelegate,UITableViewDataSource,UIAlertViewDelegate>

@property (nonatomic,strong) NSMutableArray *dataArray;

@end



@implementation TableView

-(NSMutableArray *)dataArray

{

    if (_dataArray == nil) {

        _dataArray = [[NSMutableArray alloc]init];

        for (NSInteger i = 0; i < 3; i++) {

            //设置分区

            SectionModel *sectionModel = [[SectionModel alloc]init];

            sectionModel.isExpanded = NO;

            sectionModel.sectionTitle = [NSString stringWithFormat:@"section = %ld",i];

            //设置cell

            NSMutableArray *array =  [[NSMutableArray alloc]init];

            for (NSInteger j = 0; j < 5; j++) {

                CellModel *cellModel = [[CellModel alloc]init];

                cellModel.cellTitle = [NSString stringWithFormat:@"section = %ld, row = %ld",i,j];

                cellModel.webImageUrl = [NSString stringWithFormat:@""];

                [array addObject:cellModel];

            }

            sectionModel.cellModels = array; //分区模型里面添加cell模型

            [_dataArray addObject:sectionModel];    //数据里面添加分区模型

        }

    }

    return _dataArray;

}


-(instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style

{

    if (self = [super initWithFrame:frame style:style]) {

        

        self.delegate = self;

        self.dataSource = self;

        self.showsVerticalScrollIndicator = NO;

        self.showsHorizontalScrollIndicator = NO;

        [self registerClass:[HeaderView class] forHeaderFooterViewReuseIdentifier:headerIdentifier];

    }

    return self;

}


#pragma mark UITableViewDataSource

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

{

    return self.dataArray.count;

}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

    SectionModel *sectionMocel = self.dataArray[section];

    

    return  sectionMocel.isExpanded ? sectionMocel.cellModels.count : 0;

}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString *identifier = @"TableView";

    

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];

    if (cell == nil) {

        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];

    }

    UIView *selectBg = [[UIView alloc]initWithFrame:cell.frame];

    selectBg.backgroundColor = [UIColor redColor];

    cell.selectedBackgroundView = selectBg;

    

    cell.backgroundColor = [UIColor grayColor];

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    

    SectionModel *sectionModel = self.dataArray[indexPath.section];

    CellModel *cellModel = sectionModel.cellModels[indexPath.row];

    cell.textLabel.text = cellModel.cellTitle;

    

    return cell;

}

-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath

{

    return YES;

}

#pragma mark UITableViewDelegate

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

    return 44;

}

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

{

    return headerHeight;

}

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

{

    HeaderView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerIdentifier];

    SectionModel *sectionModle = self.dataArray[section];

    headerView.model = sectionModle;

    headerView.expandCallBack = ^(BOOL isExpanded){

    

        [tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];

    };

    return headerView;

}


-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

    [tableView deselectRowAtIndexPath:indexPath animated:NO];

    

    SectionModel *sectionModel = self.dataArray[indexPath.section];

    CellModel *cellModel = sectionModel.cellModels[indexPath.row];

    NSLog(@"点击到的是%@",cellModel.cellTitle);

    

    [self alert:sectionModel.sectionTitle message:cellModel.cellTitle];

}


-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath

{

    return UITableViewCellEditingStyleDelete;

}


-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath

{

    if (editingStyle == UITableViewCellEditingStyleDelete){

        SectionModel *sectionModel = self.dataArray[indexPath.section];

        [sectionModel.cellModels removeObjectAtIndex:indexPath.row];

        NSLog(@"删除");

    }

    

    [tableView reloadData];

}


-(void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath

{

    NSLog(@"结束编辑");

}


-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath

{

    return @"点击删除";

}


-(void)alert:(NSString *)title message:(NSString *)messsage

{

    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:title message:messsage delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];

    [alert show];

}


-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

{

    //确定 取消 0

    switch (buttonIndex) {

        case 0:

            NSLog(@"0");

            break;

        case 1:

            NSLog(@"1");

            break;

            

        default:

            break;

    }

}


Controller

Controller 文件 里面就比较简单了

#import "TableView.h" //导入子类文件

- (void)viewDidLoad {

    [super viewDidLoad];

UITableView *tableView = [[TableView alloc]initWithFrame:CGRectMake(0, 100, View_Width, 300) style:UITableViewStylePlain];

    [self.view addSubview:tableView];

}


我自定义表头

#import <UIKit/UIKit.h>

#import <Foundation/Foundation.h>

@class SectionModel;


FOUNDATION_EXPORT NSString *headerIdentifier;

FOUNDATION_EXPORT CGFloat headerHeight;

typedef void(^HeaderViewExpandCallBack)(BOOL isExpanded);


@interface HeaderView : UITableViewHeaderFooterView


@property (nonatomic,strong) SectionModel *model;

@property (nonatomic,copy) HeaderViewExpandCallBack expandCallBack;

-(instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier;

@end


表头文件的是实现

#import "HeaderView.h"

#import "SectionModel.h"



NSString *headerIdentifier = @"headerIdentifier";

CGFloat headerHeight = 44;



@interface HeaderView ()


@property (nonatomic,strong) UIImageView *arrowImageView;

@property (nonatomic,strong) UILabel *titleLabel;


@end


@implementation HeaderView


-(instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier

{

    if (self = [super initWithReuseIdentifier:reuseIdentifier]) {

        

        CGFloat width = [UIScreen mainScreen].bounds.size.width;

        

        self.arrowImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"back1.png"]];

        self.arrowImageView.frame = CGRectMake(0, (44-8)/2, 15, 8);

        [self.contentView addSubview:self.arrowImageView];

        

        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

        [button addTarget:self action:@selector(onExpand:) forControlEvents:UIControlEventTouchUpInside];

        [self.contentView addSubview:button];

        button.frame = CGRectMake(0, 0, width, 44);

        

        self.titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(35, 0, 200, 44)];

        self.titleLabel.textColor = [UIColor blackColor];

        self.titleLabel.backgroundColor = [UIColor clearColor];

        [self.contentView addSubview:self.titleLabel];

        self.contentView.backgroundColor = [UIColor greenColor];

        

        UIView *line = [[UIView alloc]initWithFrame:CGRectMake(0, 43, width, 1)];

        line.backgroundColor = [UIColor lightGrayColor];

        [self.contentView addSubview:line];

        

    }

    return self;

}


//我们在配置数据的时候,也会根据isExpanded状态来显示图片的方向,否则重用后就恢复原状了。

-(void)onExpand:(UIButton *)sender

{

    self.model.isExpanded = !self.model.isExpanded;

    

    [UIView animateWithDuration:0.25 animations:^{

        

        if (self.model.isExpanded) {

            self.arrowImageView.transform = CGAffineTransformIdentity;

        }else{

            self.arrowImageView.transform = CGAffineTransformMakeRotation(M_PI);

        }

    }];

    

    if (self.expandCallBack) {

        self.expandCallBack(self.model.isExpanded);

    }

    

}


//重写setModel方法来配置数据   get 只读  set 设置

-(void)setModel:(SectionModel *)model

{

    if (_model != model) {

        _model = model;

    }

    

    if (model.isExpanded) {

        self.arrowImageView.transform = CGAffineTransformIdentity;

    }else{

        self.arrowImageView.transform = CGAffineTransformMakeRotation(M_PI);

    }

    

    self.titleLabel.text = model.sectionTitle;

}


@end










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值