iOS开发初探篇——表视图中的MVC运用
概述
本初探篇为本人学习iOS开发中的一个总结系列,为工作和业余学习中遇到的初级问题的一个初步探究。本文初探的内容是MVC设计模式在表视图中的应用。主要以探究MVC为主,至于OC基本语法和表视图的使用上的优化等问题先不考虑。首先感谢博主KC写的精彩博文。
本文主要内容如下:
1.MVC基本介绍
2.MVC在表视图中的应用
MVC基本介绍
MVC模式这个名词太熟悉,不过本人由于缺乏工程实践经验,对其理解目前还停留在理论的表面层次上。在iOS开发中MVC模式第一次在表视图设计中应用到,想借此机会对其有个初步的认识。
MVC在表视图中的对号入座,目前的理解为如下图所示:

MVC在表视图中的应用
对上图再补充说明:在定制TableViewCell中,Cell即为MVC中的View,Model中的数据一般来自网络请求得到的数据,简单的模型可以封装成由各类属性组成字典,然后字典封装到可变数组中。具体用法会在下面的内容中进行介绍。严格意义上的MVC是不允许Model和View之间进行数据访问的。但实际情况有时也不一定严格遵守。下面做一个简单的具体工程实例。
首先UI需求如下图所示,显然我们需要定制TaleView中的Cell。

1.Model的定制
我们需要通过网格请求获取到的数据有:具体的图片、具体的姓名、具体的昵称。在这里先包装成字典的形式,然后把字典传到Model中。Model根据字典的key获取Value组装成一个类供Cell使用。注意,不同的字典就可以生成不同的Model类。在这里做一个学生类的形式进行展现。具体的代码如下所示。
// // Student.h // CustomCellByCode // // Created by hushunfeng on 15-6-20. // Copyright (c) 2015年 CMCC. All rights reserved. // #import <Foundation/Foundation.h> @interface Student : NSObject @property (strong, nonatomic) UIImage *icon; @property (strong, nonatomic) NSString *name; @property (strong, nonatomic) NSString *nickname; -(Student*)initWithDictionary:(NSDictionary *)dic; @end
//
// Student.m
// CustomCellByCode
//
// Created by hushunfeng on 15-6-20.
// Copyright (c) 2015年 CMCC. All rights reserved.
//
#import "Student.h"
@implementation Student
- (Student *) initWithDictionary:(NSDictionary *)dic{
if(self = [super init]){
self.icon = dic[@"image"];
self.name = dic[@"name"];
self.nickname = dic[@"nickname"];
}
return self;
}
@end
2.Cell的定制
Cell的定制根据UI界面的实际情况来就行。此设计中,姓名:,昵称:是写死在Cell中的。需要变动的只是图片、真实姓名和真实昵称。具体代码如下。
// // MyCell.h // CustomCellByCode // // Created by hushunfeng on 14-8-27. // Copyright (c) 2014年 e世雕龙. All rights reserved. // #import <UIKit/UIKit.h> #import "Student.h" @interface MyCell : UITableViewCell @property (strong, nonatomic) UIImageView *myImageView;//头像 @property (strong, nonatomic) UILabel *nameLabel;//姓名 @property (strong, nonatomic) UILabel *nicknameLabel;//昵称 @property (strong,nonatomic) Student *stu; @end
//
// MyCell.m
// CustomCellByCode
//
// Created by hushunfeng on 15-6-20.
// Copyright (c) 2015年 CMCC. All rights reserved.
//
#import "MyCell.h"
@implementation MyCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
//创建自定义单元格中控件
//写死的
UILabel *nameLabel = [[UILabel alloc]initWithFrame:CGRectMake(160, 45, 51, 21)];
nameLabel.text = @"姓名:";
UILabel *nicknameLabel = [[UILabel alloc]initWithFrame:CGRectMake(160, 80, 51, 21)];
nicknameLabel.text = @"昵称:";
//根据model传进来的值要变动的
self.nameLabel = [[UILabel alloc]initWithFrame:CGRectMake(239, 45, 51, 21)];
self.myImageView = [[UIImageView alloc]initWithFrame:CGRectMake(10, 10, 120, 120)];
self.nicknameLabel = [[UILabel alloc]initWithFrame:CGRectMake(239, 80, 51, 21)];
//加入单元格内容视图中
[self.contentView addSubview:self.myImageView];
[self.contentView addSubview:nameLabel];
[self.contentView addSubview:self.nameLabel];
[self.contentView addSubview:nicknameLabel];
[self.contentView addSubview:self.nicknameLabel];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#pragma mark 绑定model传进来的数据的方法
- (void)bind:(Student *)stu {
self.myImageView.image = stu.icon;
self.nameLabel.text = stu.name;
self.nicknameLabel.text = stu.nickname;
}
@end
3.ViewController
// // MainViewController.h // CustomCellByCode // // Created by hushunfeng on 15-6-20. // Copyright (c) 2014年 CMCC. All rights reserved. // #import <UIKit/UIKit.h> @interface MainViewController:UIViewController <UITableViewDataSource,UITableViewDelegate> @end
//
// MainViewController.m
// CustomCellByCode
//
// Created by hushufeng on 15-6-20.
// Copyright (c) 2014年 CMCC. All rights reserved.
//
#import "MainViewController.h"
#import "Student.h"
#import "MyCell.h"
@interface MainViewController ()
@property (strong,nonatomic) UITableView *tableView;
@property (strong, nonatomic) NSMutableArray *students;//数据源
@end
@implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height) style:UITableViewStylePlain];
self.tableView.dataSource = self;
self.tableView.delegate = self;
[self.view addSubview:self.tableView];
//准备数据源
UIImageView *view1 = [[UIImageView alloc]init];
view1.image = [UIImage imageNamed:@"guan"];
UIImageView *view2 = [[UIImageView alloc]init];
view2.image = [UIImage imageNamed:@"hejin"];
UIImageView *view3 = [[UIImageView alloc]init];
view3.image = [UIImage imageNamed:@"tang"];
NSDictionary *dic1 = @{@"image":view1.image,
@"name":@"孙悟空",
@"nickname":@"猴子"};
NSDictionary *dic2 = @{@"image":view2.image,
@"name":@"八戒",
@"nickname":@"呆子"};
NSDictionary *dic3 = @{@"image":view3.image,
@"name":@"唐僧",
@"nickname":@"三藏"};
Student *model1 = [[Student alloc]initWithDictionary:dic1];
Student *model2 = [[Student alloc]initWithDictionary:dic2];
Student *model3 = [[Student alloc]initWithDictionary:dic3];
//
self.students = [[NSMutableArray alloc]init];
[self.students addObject:model1];
[self.students addObject:model2];
[self.students addObject:model3];
// self.students = [NSArray arrayWithObjects:model1,model2,model3, nil];
}
#pragma mark - Table view data source
//该数据源方法指定表视图有几个分区
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
//该数据源方法指定表视图每个分区有几行数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return self.students.count;
}
//该数据源方法指定表视图如何显示数据
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//创建可重用标识符
static NSString *cellID = @"cellID";
//首先从出列可重用队列中获取单元格
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
//如果没有则创建单元格
if (!cell) {
cell = [[MyCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
// //获取Student对象
Student *stu = [[Student alloc]init];
stu = self.students[indexPath.row];
[cell bind:stu];//绑定数据
return cell;
}
#pragma mark 该数据源方法指定单元格的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 141;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
效果图:

浙公网安备 33010602011771号