ios实战开发之代码创建Cell(演示新浪微博)
本帖最后由 Sian 于 2014-4-18 14:02 编辑1、效果演示
http://player.youku.com/player.php/sid/XNjk3MDQyMDA4/v.swf
2、设计说明
2.0 设计草图
2.1 模型说明
2.1.1 SAWeibo类:该类主要功能是将基本数据抽象成数据模型,将数据处理思想转换成面向对象的理念;
2.1.2 SAWeiboFrame类:该类是新增加的一个类,将各视图尺寸位置的设置单独抽象出来创建一个视图框架模型,该模型中包含了数据模型,给每条微博提供数据源及各子视图子控件提供位置与尺寸服务;
2.1.3 SAWeiboCell类:该类主要功能是创建TableView中每个Cell的内容,包含数据与视图,因此将SAWeiboFrame添加给该类的一个成员变量,调用SAWeibo类与SAWeiboFrame类完成微博展示功能;
2.2 基本步骤
2.2.1 删除原有的控制器,新建一个控制器SAWeiboController直接继承自UITableViewController,删除storyboard中的view,新建一个UITableView并将UITableView的类设置为新创建的控制器
2.2.2 新建一个类SAWeiboCell继承自UITabeViewCell,该类主要功能在2.1 模型说明中已描述;
2.2.3 在控制器SAWeiboController中实现必须实现的几个方法,如numberOfRowsInSection、cellForRowAtIndexPath、heightForRowAtIndexPath等方法
2.2.4 在实现cellForRowAtIndexPath方法前需要创建SAWeiboCell类,并在该类中实现Cell创建的initWithStyle:reuseIdentifier:方法,添加cell内部需要的子控件(此时只管添加控件暂不关心控件的尺寸与位置);
2.2.5 创建数据模型SAWeibo类,增加相应的数据属性;
2.2.6 创建视图框架模型SAWeiboFrame类,增加相应的数据属性并将数据模型设置成该模型的属性;
2.2.7 重写setWeibo方法,将数据模型赋值的同时将所有子控件的尺寸与位置进行计算确定、将在最后计算出每个Cell的高度
2.2.8 将计算得出来的值分别写到各属性中,回到控制器完善控制器未完成的配置;
2.2.9 将数据模型赋值,将视图框架模型赋值,并将相关属性结果回写到numberOfRowsInSection、cellForRowAtIndexPath、heightForRowAtIndexPath方法中
3、关键代码
SAWeibo.h
//
//SAWeibo.h
//
//Created by yusian on 14-4-10.
//Copyright (c) 2014年 yusian. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SAWeibo : NSObject
@property (nonatomic, copy) NSString *icon; // 头像
@property (nonatomic, copy) NSString *name; // 昵称
@property (nonatomic, assign) BOOL isVip; // vip标识
@property (nonatomic, copy) NSString *time; // 发表时间
@property (nonatomic, copy) NSString *source; // 微博来源
@property (nonatomic, copy) NSString *content; // 微博内容
@property (nonatomic, copy) NSString *image; // 微博配图
+ (id)weiboWithDict:(NSDictionary *)dict; // 模型赋值类方法
- (id)initWithDict:(NSDictionary *)dict; // 模型赋值对象方法
@end
SAWeibo.m
//
//SAWeibo.m
//
//Created by yusian on 14-4-10.
//Copyright (c) 2014年 yusian. All rights reserved.
//
#import "SAWeibo.h"
@implementation SAWeibo
+ (id)weiboWithDict:(NSDictionary *)dict
{
return [ initWithDict:dict]; // 调用对象方法初始化数据模型
}
// 取出字典中的每个Key中对应的值赋值给数据模型
- (id)initWithDict:(NSDictionary *)dict
{
if (self = ) {
self.icon = dict[@"icon"]; // 头像图片名称
self.name = dict[@"name"]; // 昵称
self.time = dict[@"time"]; // 发表时间
self.source = dict[@"source"]; // 微博来源
self.isVip = boolValue];// vip标识,Number类型转成BOOL类型
self.content = dict[@"content"]; // 微博正文
self.image = dict[@"image"]; // 微博配图图片名称
}
return self;
}
@end
SAWeiboFrame.h
//
//SAWeiboFrame.h
//
//Created by yusian on 14-4-10.
//Copyright (c) 2014年 yusian. All rights reserved.
//
#import <Foundation/Foundation.h>
#define kIconWH 40 // 头像宽高
#define kInterval 10 // 全局间距
#define kVipWH14 // vip标识宽高
#define kImageWH 200 // 微博配图宽高
#define kNameFont // 昵称字号大小
#define kTimeFont // 发表时间字号大小
#define kSourceFont // 微博来源字号大小
#define kContentFont // 微博正文字号大小
@class SAWeibo;
@interface SAWeiboFrame : NSObject
@property (nonatomic, assign, readonly) CGRecticonViewFrame; // 头像尺寸位置
@property (nonatomic, assign, readonly) CGRectnameLabelFrame; // 昵称尺寸位置
@property (nonatomic, assign, readonly) CGRecttimeLabelFrame; // 发表时间尺寸位置
@property (nonatomic, assign, readonly) CGRectvipViewFrame; // vip标识尺寸位置
@property (nonatomic, assign, readonly) CGRectsourceLabelFrame; // 微博来源尺寸位置
@property (nonatomic, assign, readonly) CGRectcontentLabelFrame;// 微博正文尺寸位置
@property (nonatomic, assign, readonly) CGRectimageViewFrame; // 微博配图尺寸位置
@property (nonatomic, assign, readonly) CGFloat cellHeight; // 每条微博Cell高度
@property (nonatomic, strong) SAWeibo *weibo; // 数据模型
@end
SAWeiboFrame.m
//
//SAWeiboFrame.m
//
//Created by yusian on 14-4-10.
//Copyright (c) 2014年 yusian. All rights reserved.
//
#import "SAWeiboFrame.h"
#import "SAWeibo.h"
@implementation SAWeiboFrame
// 在数据模型set方法中将各子视图的尺寸大小及每条微博的行高进行计算与确定
- (void)setWeibo:(SAWeibo *)weibo
{
_weibo = weibo; // 将创建好的模型对象赋值给成员变量,让模型数据成为视图框架模型的属性
// 1、头像
CGFloat iconX = kInterval;
CGFloat iconY = kInterval;
_iconViewFrame = CGRectMake(iconX, iconY, kIconWH, kIconWH);
// 2、昵称
CGFloat nameX = CGRectGetMaxX(_iconViewFrame) + kInterval;
// CGRectGetMaxX(_iconViewFrame)为取头像Frame中X最大值
CGFloat nameY = iconY;
CGSize nameSize = ;
// 字符串方法,意为该字符串在某种字体状态下所占据的尺寸
_nameLabelFrame = CGRectMake(nameX, nameY, nameSize.width, nameSize.height);
// 3、vip
CGFloat vipX = CGRectGetMaxX(_nameLabelFrame) + kInterval;
CGFloat vipY = iconY;
_vipViewFrame = CGRectMake(vipX, vipY, kVipWH, kVipWH);
// 4、时间
CGFloat timeX = nameX;
CGFloat timeY = CGRectGetMaxY(_nameLabelFrame) + kInterval;
CGSize timeSize = ;
_timeLabelFrame = CGRectMake(timeX, timeY, timeSize.width, timeSize.height);
// 5、来源
CGFloat sourceX = CGRectGetMaxX(_timeLabelFrame) + kInterval;
CGFloat sourceY = timeY;
NSString *sourceText = ;
CGSize sourceSize = ;
// 计算尺寸应为实际显示内容的尺寸,所以取拼串后字符串的sizeWithFont:方法
_sourceLabelFrame = CGRectMake(sourceX, sourceY, sourceSize.width, sourceSize.height);
// 6、正文
CGFloat contentX = iconX;
CGFloat contentY = MAX(CGRectGetMaxY(_iconViewFrame), CGRectGetMaxY(_timeLabelFrame)) + kInterval;
// 正文与上面子视图保持一个全局间隔距离,但无法确定头像与发表时间哪个子视图下边缘Y值更大,所以利用宏MAX(A, B)对这两个子视图进行比较,以最大值为标准
CGFloat contentWidth = 320 - 2 * kInterval;
// 正文宽度保持屏幕两侧预算一个全局间隔距离即可
CGSize contentSize = ;
_contentLabelFrame = CGRectMake(contentX, contentY, contentSize.width, contentSize.height);
// 7、配图
if (self.weibo.image) {
CGFloat imageX = contentX;
CGFloat imageY = CGRectGetMaxY(_contentLabelFrame) + kInterval;
_imageViewFrame = CGRectMake(imageX, imageY, kImageWH, kImageWH);
// 如果有配图,则每条微博高度以配图下边缘Y值为基准
_cellHeight = CGRectGetMaxY(_imageViewFrame) + kInterval;
} else {
// 如果没有配置,则每条微博高度以正文下边缘Y值为基准
_cellHeight = CGRectGetMaxY(_contentLabelFrame) + kInterval;
}
}
@end
SAWeiboCell.h
//
//SAWeiboCell.h
//
//Created by yusian on 14-4-10.
//Copyright (c) 2014年 yusian. All rights reserved.
//
#import <UIKit/UIKit.h>
@class SAWeiboFrame;
@interface SAWeiboCell : UITableViewCell
@property (nonatomic, strong) SAWeiboFrame *weiboFrame; // 让视图框架模型成为Cell模型的属性
+ (NSString *)ID; // 封装tableView的缓存cell标识
@end
SAWeiboCell.m
//
//SAWeiboCell.m
//
//Created by yusian on 14-4-10.
//Copyright (c) 2014年 yusian. All rights reserved.
//
#import "SAWeiboCell.h"
#import "SAWeiboFrame.h"
#import "SAWeibo.h"
@interface SAWeiboCell () // 类扩展成员变量
{
UIImageView *_iconView; // 头像
UIImageView *_vipView; // vip标识
UILabel *_nameLabel; // 昵称
UILabel *_sourceLabel; // 微博来源
UILabel *_timeLabel; // 发表时间
UILabel *_contentLabel; // 微博正文
UIImageView *_imageView; // 微博配图
}
@end
@implementation SAWeiboCell
#pragma mark cell初始化方法
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = ) {
// 1、头像
_iconView = [ init];
;
// 2、昵称
_nameLabel = [ init];
_nameLabel.font = kNameFont;
;
// 3、vip标识
_vipView = [ init];
_vipView.image = ;
;
// 4、发表时间
_timeLabel = [ init];
_timeLabel.font = kTimeFont;
_timeLabel.textColor = ;
;
// 5、微博来源
_sourceLabel = [ init];
_sourceLabel.font = kSourceFont;
_sourceLabel.textColor = ;
;
// 6、正文
_contentLabel = [ init];
_contentLabel.font = kContentFont;
;
// 7、配图
_imageView = [ init];
;
}
return self;
}
#pragma mark 成员变量weiboFrame的set方法
- (void)setWeiboFrame:(SAWeiboFrame *)weiboFrame
{
_weiboFrame = weiboFrame; // 将创建好的Frame对象赋值给成员变量
; // 设置子视图数据
; // 设置子视图尺寸及位置
}
// 调用微博数据模型设置每条微博中子视图数据内容
- (void)settingView
{
// 1、头像
_iconView.image = ;
// 2、昵称
_nameLabel.text = _weiboFrame.weibo.name;
if (_weiboFrame.weibo.isVip) {
_nameLabel.textColor = ; // 带vip标识的用户昵称显示为红色
} else {
_nameLabel.textColor = ; // 非vip用户昵称显示为黑色
}
// 3、vip
_vipView.hidden = !_weiboFrame.weibo.isVip;
// 4、时间
_timeLabel.text = _weiboFrame.weibo.time;
// 5、来源
_sourceLabel.text = ;
// 6、正文
_contentLabel.text = _weiboFrame.weibo.content;
_contentLabel.numberOfLines = 0; // 多行文本
// 7、配图
if (_weiboFrame.weibo.image) {
_imageView.hidden = NO;
_imageView.image = ;
_imageView.contentMode = UIViewContentModeScaleAspectFit;
// 图片显示模式为最大化填充,非拉伸效果,不改变图片宽高比
} else {
_imageView.hidden = YES;
}
}
// 调用子视图框架模型设置每条微博中子视图的尺寸及位置
- (void)settingFrame
{
// 1、头像
_iconView.frame = _weiboFrame.iconViewFrame;
// 2、昵称
_nameLabel.frame = _weiboFrame.nameLabelFrame;
// 3、vip
_vipView.frame = _weiboFrame.vipViewFrame;
// 4、时间
_timeLabel.frame = _weiboFrame.timeLabelFrame;
// 5、来源
_sourceLabel.frame = _weiboFrame.sourceLabelFrame;
// 6、正文
_contentLabel.frame = _weiboFrame.contentLabelFrame;
// 7、配图
_imageView.frame = _weiboFrame.imageViewFrame;
}
// 封装tableView缓存中重复利用Cell的标识
+(NSString *)ID
{
return @"Weibo";
}
@end
SAWeiboController.h
//
//SAWeiboController.h
//
//Created by yusian on 14-4-10.
//Copyright (c) 2014年 yusian. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface SAWeiboController : UITableViewController
@end
SAWeiboController.m
//
//SAWeiboController.m
//
//Created by yusian on 14-4-10.
//Copyright (c) 2014年 yusian. All rights reserved.
//
#import "SAWeiboController.h"
#import "SAWeibo.h"
#import "SAWeiboFrame.h"
#import "SAWeiboCell.h"
@interface SAWeiboController ()
{
NSMutableArray *_weiboFrames; // 可变数据保存视图框架模型
}
@end
@implementation SAWeiboController
- (void)viewDidLoad
{
;
_weiboFrames = ;
// 将plist文件读取到数据,原始数据
NSArray *array = pathForResource:@"Weibo.plist" ofType:nil]];
for (NSDictionary *dict in array) {
SAWeiboFrame *weiboFrame = [ init]; // 创建视图框架模型
weiboFrame.weibo = ; // 将原始数据转换成数据模型
; // 视图框架模型保存到数组
}
// 利用tableView缓存数据机制中的一个特别处理方式,如果缓存中没有则调用相关类创建
forCellReuseIdentifier:];
/*等同于以下代码
if (cell == nil) {
cell = [ initWithStyle:UITableViewCellStyleDefault reuseIdentifier:];
}*/
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _weiboFrames.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 缓存中取相关对象重复利用
SAWeiboCell *cell = ];
// 将数据视图框架模型(该模型中包含了数据模型)赋值给Cell,展示每条微博内容
cell.weiboFrame = _weiboFrames;
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 调用视图框架模型返回每条微博动态高度
return cellHeight];
}
@end
4、源代码下载
**** Hidden Message *****
页:
[1]