1、效果演示
2、设计说明
2.0 无相关基础请先参照前面几讲的内容
2.1 设计框架模型SAStatusFrame类,用来保存微博内容及各控件尺寸与位置,参考链接:ios实战开发之代码创建Cell(演示新浪微博)
2.2 修改SAStatusTool类,修改数据模型数组(之前数据模型数组保存的对象为SAStatus模型,现保存SAStatusFrame模型)
2.3 设计SAStatueCell类,自定义TableViewCell,参考链接:ios实战开发之代码创建Cell(演示新浪微博)
2.4 数据模型初始化之后已将各Cell的尺寸位置及内容均已计算好,因此,直接将取数据模型中的值即可轻松准确展示各Cell的值及视图
2.5 参考模型图:
3、关键代码
SAStatus.h
[Objective-C] 纯文本查看 复制代码 //
// SAStatus.h
// SianWeibo
//
// Created by yusian on 14-4-16.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SAStatusUser.h"
@interface SAStatus : NSObject
@property (nonatomic, copy) NSString *text; // 正文
@property (nonatomic, strong) SAStatusUser *user; // 用户
@property (nonatomic, copy) NSString *createdAt; // 创建时间
@property (nonatomic, copy) NSString *source; // 来源
@property (nonatomic, strong) SAStatus *retweetedStatus; // 转发体
@property (nonatomic, assign) NSInteger repostsCount; // 转发数
@property (nonatomic, assign) NSInteger commentsCount; // 评论数
@property (nonatomic, assign) NSInteger attitudesCount; // 点赞数
@property (nonatomic, strong) NSArray *picUrls; // 配图
- (id)initWithDict:(NSDictionary *)dict;
+ (id)statusWithDict:(NSDictionary *)dict;
@end
SAStatus.m
[Objective-C] 纯文本查看 复制代码 //
// SAStatus.m
// SianWeibo
//
// Created by yusian on 14-4-16.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import "SAStatus.h"
@implementation SAStatus
- (id)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
self.text = dict[@"text"]; // 正文
self.user = [SAStatusUser statusUserWithDict:dict[@"user"]]; // 用户
self.createdAt = dict[@"created_at"]; // 创建时间
self.source = dict[@"source"]; // 来源
self.repostsCount = [dict[@"reposts_count"] intValue]; // 转发数
self.commentsCount = [dict[@"comments_count"] intValue]; // 评论数
self.attitudesCount = [dict[@"attitudes_count"] intValue]; // 点赞数
self.picUrls = dict[@"pic_urls"]; // 配图
NSDictionary *retweetedStatus = dict[@"retweeted_status"];
if (retweetedStatus) { // 转发体(被转载的微博内容)
self.retweetedStatus = [[SAStatus alloc] initWithDict:retweetedStatus];
}
}
return self;
}
+ (id)statusWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
@end
SAStatusUser.h
[Objective-C] 纯文本查看 复制代码 //
// SAStatusUser.h
// SianWeibo
//
// Created by yusian on 14-4-16.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SAStatusUser : NSObject
@property (nonatomic, copy) NSString *screenName; // 昵称
@property (nonatomic, copy) NSString *profileImageUrl; // 头像
@property (nonatomic, assign) BOOL verified; // 是否验证
@property (nonatomic, assign) NSInteger verifiedType; // 验证类型
@property (nonatomic, assign) NSInteger mbrank; // 会员等级
@property (nonatomic, assign) NSInteger mbtype; // 会员类型
- (id)initWithDict:(NSDictionary *)dict;
+ (id)statusUserWithDict:(NSDictionary *)dict;
@end
SAStatusUser.m
[Objective-C] 纯文本查看 复制代码 //
// SAStatusUser.m
// SianWeibo
//
// Created by yusian on 14-4-16.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import "SAStatusUser.h"
@implementation SAStatusUser
- (id)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
self.screenName = dict[@"screen_name"]; // 昵称
self.profileImageUrl = dict[@"profile_image_url"]; // 头像
self.verified = [dict[@"verified"] boolValue]; // 是否验证
self.verifiedType = [dict[@"verified_type"] integerValue]; // 验证类型
self.mbrank = [dict[@"mbrank"] integerValue]; // 会员等级
self.mbtype = [dict[@"mbtype"] integerValue]; // 会员类型
}
return self;
}
+ (id)statusUserWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
@end
SAStatusFrame.h
[Objective-C] 纯文本查看 复制代码 //
// SAStatusFrame.h
// SianWeibo
//
// Created by yusian on 14-4-18.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SAStatus.h"
#define kInterval 10
#define kProfileWH 40
#define kScreenNameFount [UIFont systemFontOfSize:16]
#define kTimeFont [UIFont systemFontOfSize:13]
#define kSourceFont kTimeFont
#define kTextFount [UIFont systemFontOfSize:15]
#define kReScreenNameFont [UIFont systemFontOfSize:14]
#define kReTextFont kReScreenNameFont
@interface SAStatusFrame : NSObject
@property (nonatomic, readonly) CGRect profile; // 头像
@property (nonatomic, readonly) CGRect screenName; // 昵称
@property (nonatomic, readonly) CGRect time; // 时间
@property (nonatomic, readonly) CGRect source; // 来源
@property (nonatomic, readonly) CGRect text; // 正文
@property (nonatomic, readonly) CGRect image; // 配图
@property (nonatomic, readonly) CGRect retweet; // 转发体视图
@property (nonatomic, readonly) CGRect reScreenName; // 转发体昵称
@property (nonatomic, readonly) CGRect reText; // 转发体正文
@property (nonatomic, readonly) CGRect reImage; // 转发体配图
@property (nonatomic, readonly) CGFloat cellHeight; // 行高
@property (nonatomic, strong) SAStatus *status; // 数据模型
@end
SAStatusFrame.m
[Objective-C] 纯文本查看 复制代码 //
// SAStatusFrame.m
// SianWeibo
//
// Created by yusian on 14-4-18.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import "SAStatusFrame.h"
@implementation SAStatusFrame
-(void)setStatus:(SAStatus *)status
{
_status = status;
CGSize screenSize = [UIScreen mainScreen].applicationFrame.size;
// 1、设置头像尺寸位置;
CGFloat profileX = kInterval;
CGFloat profileY = kInterval;
_profile = CGRectMake(profileX, profileY, kProfileWH, kProfileWH);
// 2、设置昵称尺寸位置;
CGFloat screenNameX = CGRectGetMaxX(_profile) + kInterval;
CGFloat screenNameY = profileY;
CGSize screenNameSize = [status.user.screenName sizeWithFont:kScreenNameFount];
_screenName = (CGRect){{screenNameX, screenNameY}, screenNameSize};
// 3、设置时间尺寸位置
CGFloat timeX = screenNameX;
CGFloat timeY = CGRectGetMaxY(_screenName);
CGSize timeSize = [status.createdAt sizeWithFont:kTimeFont];
_time = (CGRect){{timeX, timeY}, timeSize};
// 4、设置来源尺寸位置
CGFloat sourceX = CGRectGetMaxX(_time) + kInterval;
CGFloat sourceY = timeY;
CGSize sourceSize = [status.source sizeWithFont:kSourceFont];
_source = (CGRect){{sourceX, sourceY}, sourceSize};
// 5、设置正文尺寸位置;
CGFloat textX = profileX;
CGFloat textY = MAX (CGRectGetMaxY(_profile), CGRectGetMaxY(_time)) + kInterval;
CGFloat textW = screenSize.width - 2 * kInterval;
CGSize textSize = [_status.text sizeWithFont:kTextFount constrainedToSize:CGSizeMake(textW, MAXFLOAT)];
_text = (CGRect){{textX, textY}, textSize};
if (_status.picUrls.count) { // 第一种情况:带配图的微博
// 6、设置配图尺寸位置
CGFloat imageX = profileX;
CGFloat imageY = CGRectGetMaxY(_text) + kInterval;
CGSize imageSize = {100, 100};
_image = (CGRect){{imageX, imageY}, imageSize};
// 有配图无转发体单元格高度
_cellHeight = CGRectGetMaxY(_image) + kInterval;
} else if (_status.retweetedStatus) { // 第二种情况:转发的微博
// 7、设置转发体尺寸位置
CGFloat retweetX = profileX;
CGFloat retweetY = CGRectGetMaxY(_text) + kInterval;
CGFloat retweetW = screenSize.width - 2 * kInterval;
CGFloat retweetH = kInterval;
_retweet = CGRectMake(retweetX, retweetY, retweetW, retweetH);
// 8、设置转发体昵称尺寸位置
CGFloat reScreenNameX = kInterval;
CGFloat reScreenNameY = kInterval;
CGSize reScreenNameSize = [[NSString stringWithFormat:@"@%@", _status.retweetedStatus.user.screenName] sizeWithFont:kReScreenNameFont];
_reScreenName = (CGRect){{reScreenNameX, reScreenNameY}, reScreenNameSize};
// 9、设置转发体正文尺寸位置
CGFloat reTextX = reScreenNameX;
CGFloat reTextY = CGRectGetMaxY(_reScreenName) + kInterval;
CGSize reTextSize = [_status.retweetedStatus.text sizeWithFont:kReTextFont constrainedToSize:CGSizeMake((screenSize.width - 4 * kInterval), MAXFLOAT)];
_reText = (CGRect){{reTextX, reTextY}, reTextSize};
// 10、设置转发体配图尺寸位置
if (_status.retweetedStatus.picUrls) { // 第二种情况:1、转发的微博带图
CGFloat reImageX = reScreenNameX;
CGFloat reImageY = CGRectGetMaxY(_reText) + kInterval;
CGSize reImageSize = {100, 100};
_reImage = (CGRect){{reImageX, reImageY}, reImageSize};
// 转发体有配图转发体尺寸
retweetH = CGRectGetMaxY(_reImage) + kInterval;
_retweet = CGRectMake(retweetX, retweetY, retweetW, retweetH);
} else { // 第二种情况:2、转发的微博不带图
// 转发体无配图转发体尺寸
retweetH = CGRectGetMaxY(_reText) + kInterval;
_retweet = CGRectMake(retweetX, retweetY, retweetW, retweetH);
}
// 有转发体的单元格高度
_cellHeight = CGRectGetMaxY(_retweet) + kInterval;
} else { // 第三种情况:不带配图的普通微博
// 11、设置单元格高度尺寸位置
// 无配图,无转发体单元格高度
_cellHeight = CGRectGetMaxY(_text) + kInterval;
}
}
@end
SAStatusTool.m
[Objective-C] 纯文本查看 复制代码 //
// SAStatusTool.m
// SianWeibo
//
// Created by yusian on 14-4-16.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import "SAStatusTool.h"
#import "SAStatusFrame.h"
#import "SAHttpTool.h"
@implementation SAStatusTool
+ (void)statusToolGetStatusSuccess:(StatusSuccess)success failurs:(StatusFailurs)failure
{
[[self alloc] initWithHttpToolStatusSuccess:success failurs:failure];
}
- (void)initWithHttpToolStatusSuccess:(StatusSuccess)success failurs:(StatusFailurs)failure
{
// 调用SAHttpTool这个工具类,发送相关请求返回数组内容
[SAHttpTool httpToolPostWithBaseURL:kBaseURL path:@"2/statuses/home_timeline.json" params:
@{
@"count" : @"40"
} success:^(id JSON) {
// 如果方法调用没有实现success部分,则方法直接返回
if (success == nil) return;
// 1、将返回的JSON转换成微博模型并保存到数组
NSMutableArray *statuses = [NSMutableArray array];
for (NSDictionary *dict in JSON[@"statuses"]) {
// 将JSON中解析的数据保存到框架模型中
SAStatusFrame *statusFrame = [[SAStatusFrame alloc] init];
statusFrame.status = [SAStatus statusWithDict:dict];
[statuses addObject:statusFrame];
}
// 2、将数组返回给Block形参供方法调用者使用
success(statuses);
} failure:^(NSError *error) {
if (failure == nil) return;
failure(error);
} method:@"GET"];
}
@end
SAStatusCell.h
[Objective-C] 纯文本查看 复制代码 //
// SAStatusCell.h
// SianWeibo
//
// Created by yusian on 14-4-18.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "SAStatusFrame.h"
@interface SAStatusCell : UITableViewCell
@property (nonatomic, strong) SAStatusFrame *statusFrame;
+ (NSString *)ID;
@end
SAStatusCell.m
[Objective-C] 纯文本查看 复制代码 //
// SAStatusCell.m
// SianWeibo
//
// Created by yusian on 14-4-18.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import "SAStatusCell.h"
#import "UIImageView+WebCache.h"
@interface SAStatusCell ()
{
UIImageView *_profile; // 头像
UILabel *_screenName; // 昵称
UILabel *_time; // 时间
UILabel *_source; // 来源
UILabel *_text; // 正文
UIImageView *_image; // 配图
UIImageView *_retweet; // 转发体视图
UILabel *_reScreenName; // 转发体昵称
UILabel *_reText; // 转发体正文
UIImageView *_reImage; // 转发体配图
}
@end
@implementation SAStatusCell
#pragma mrak 初始化单元格元素
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// 1、头像
_profile = [[UIImageView alloc] init];
[self.contentView addSubview:_profile];
// 2、昵称
_screenName = [[UILabel alloc] init];
_screenName.font = kScreenNameFount;
[self.contentView addSubview:_screenName];
// 3、时间
_time = [[UILabel alloc] init];
_time.font = kTimeFont;
[self.contentView addSubview:_time];
// 4、来源
_source = [[UILabel alloc] init];
_source.font = kSourceFont;
[self.contentView addSubview:_source];
// 5、正文
_text = [[UILabel alloc] init];
_text.font = kTextFount;
_text.numberOfLines = 0;
[self.contentView addSubview:_text];
// 6、配图
_image = [[UIImageView alloc] init];
_image.contentMode = UIViewContentModeScaleAspectFit;
[self.contentView addSubview:_image];
// 7、转发体视图
_retweet = [[UIImageView alloc] init];
_retweet.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1];
[self.contentView addSubview:_retweet];
// 8、转发体昵称
_reScreenName = [[UILabel alloc] init];
_reScreenName.font = kReScreenNameFont;
_reScreenName.backgroundColor = [UIColor clearColor];
_reScreenName.textColor = [UIColor blueColor];
[_retweet addSubview:_reScreenName];
// 9、转发体正文
_reText = [[UILabel alloc] init];
_reText.numberOfLines = 0;
_reText.font = kReTextFont;
_reText.backgroundColor = [UIColor clearColor];
[_retweet addSubview:_reText];
// 10、转发体配图
_reImage = [[UIImageView alloc] init];
_reImage.contentMode = UIViewContentModeScaleAspectFit;
[_retweet addSubview:_reImage];
}
return self;
}
#pragma mark - 设置单元格
-(void)setStatusFrame:(SAStatusFrame *)statusFrame
{
_statusFrame = statusFrame;
[self statusFrameSettingView];
[self statusFrameSettingFrame];
}
#pragma mark 设置单元格内容
- (void)statusFrameSettingView
{
SAStatus *status = self.statusFrame.status;
// 1、设置头像
[_profile setImageWithURL:[NSURL URLWithString:status.user.profileImageUrl]
placeholderImage:[UIImage imageNamed:@"Icon.png"]
options:SDWebImageRetryFailed | SDWebImageLowPriority];
// 2、设置昵称
_screenName.text = status.user.screenName;
// 3、设置时间
_time.text = status.createdAt;
// 4、设置来源
_source.text = status.source;
// 5、设置正文
_text.text = status.text;
// 6、设置配图
if (status.picUrls.count) { // 第一种情况:带有配图的微博
_image.hidden = NO;
_retweet.hidden = YES;
[_image setImageWithURL:[NSURL URLWithString:status.picUrls[0][@"thumbnail_pic"]] placeholderImage:[UIImage imageNamed:@"Icon.png"] options:SDWebImageLowPriority | SDWebImageRetryFailed];
} else if (status.retweetedStatus) { // 第二种情况:转发的微博
_image.hidden = YES;
_retweet.hidden = NO;
// 7、设置转发体昵称
_reScreenName.text = [NSString stringWithFormat:@"@%@", status.retweetedStatus.user.screenName];
// 8、转发体正文
_reText.text = status.retweetedStatus.text;
// 9、转发体配图
if (status.retweetedStatus.picUrls.count) { // 第二种情况:1、转发的微博带配图
// 设置转发体图片内容(暂时取一张为例)
_reImage.hidden = NO;
[_reImage setImageWithURL:[NSURL URLWithString:status.retweetedStatus.picUrls[0][@"thumbnail_pic"]] placeholderImage:[UIImage imageNamed:@"Icon.png"] options:SDWebImageLowPriority | SDWebImageRetryFailed];
} else { // 第二种情况:2、转发的微博不带配图
// 无配图则清空属性并隐藏
_reImage.hidden = YES;
}
} else { // 第三种情况:不带配图的微博
_image.hidden = YES;
_retweet.hidden = YES;
}
}
#pragma mark 单元格元素布局
- (void)statusFrameSettingFrame
{
// 1、设置头像尺寸位置
_profile.frame = _statusFrame.profile;
// 2、设置昵称尺寸位置
_screenName.frame = _statusFrame.screenName;
// 3、设置时间尺寸位置
_time.frame = _statusFrame.time;
// 4、设置来源尺寸位置
_source.frame = _statusFrame.source;
// 5、设置正文尺寸位置
_text.frame = _statusFrame.text;
// 6、设置配图尺寸位置
_image.frame = _statusFrame.image;
// 7、设置转发体尺寸位置
_retweet.frame = _statusFrame.retweet;
// 8、设置转发体昵称尺寸位置
_reScreenName.frame = _statusFrame.reScreenName;
// 9、转发体正文尺寸位置
_reText.frame = _statusFrame.reText;
// 10、转发体配图尺寸位置
_reImage.frame = _statusFrame.reImage;
}
#pragma mark 设置单元格标识
+ (NSString *)ID
{
return @"StatusCell";
}
@end
SAHomeController.m
[Objective-C] 纯文本查看 复制代码 //
// SAHomeController.m
// SianWeibo
//
// Created by yusian on 14-4-12.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
// 首页控制器
#import "SAHomeController.h"
#import "NSString+SA.h"
#import "UIBarButtonItem+SA.h"
#import "SAStatusTool.h"
#import "UIImageView+WebCache.h"
#import "SAStatusCell.h"
@interface SAHomeController ()
{
NSArray *_statusFrame; // 框架模型数组
}
@end
@implementation SAHomeController
#pragma mark - 初始化方法
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
#pragma mark - 界面内容展示
- (void)viewDidLoad
{
[super viewDidLoad];
// self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_statusFrame = [NSMutableArray array];
// 1、设置基本界面
[self loadBasicUI];
// 2、加载数据
[self loadStatusData];
}
#pragma mark 加载基本界面
- (void)loadBasicUI
{
self.title = @"首页";
// 用自定的分类方法给导航条添加左边按钮
self.navigationItem.leftBarButtonItem = [UIBarButtonItem barButtonItemWithImageName:@"navigationbar_compose.png" highLightedImageName:@"navigationbar_compose_highlighted.png" addTarget:self action:@selector(leftButtonClick) forControlEvents:UIControlEventTouchUpInside];
// 用自定的分类方法给导航条添加右边按钮
self.navigationItem.rightBarButtonItem = [UIBarButtonItem barButtonItemWithImageName:@"navigationbar_pop.png" highLightedImageName:@"navigationbar_pop_highlighted.png" addTarget:self action:@selector(rightButtonClick) forControlEvents:UIControlEventTouchUpInside];
}
#pragma mark 加载微博数据
- (void)loadStatusData
{
// 调用SAStatusTool方法直接加载数据到模型数组
[SAStatusTool statusToolGetStatusSuccess:^(NSArray *array) {
_statusFrame = [NSArray arrayWithArray:array];
[self.tableView reloadData];
} failurs:^(NSError *error) {
MyLog(@"%@", [error localizedDescription]);
}];
}
#pragma mark - 单元格属性
#pragma mark 总单元格行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// 框架模型个数即为单元格数
return _statusFrame.count;
}
#pragma mark 单元格内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
SAStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:[SAStatusCell ID]];
if (cell == nil){
cell = [[SAStatusCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[SAStatusCell ID]];
}
// 单元格内容由框架模型提供
cell.statusFrame = _statusFrame[indexPath.row];
return cell;
}
#pragma mark 单元格高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 取对应框架模型中的单元格高度属性
return [_statusFrame[indexPath.row] cellHeight];
}
#pragma mark - 按钮事件处理
#pragma mark 首页导航左按钮事件
- (void)leftButtonClick
{
MyLog(@"首页左按钮");
}
#pragma mark 首页导航右按钮事件
- (void)rightButtonClick
{
MyLog(@"首页右按钮");
}
@end
4、源码下载
相关主题链接
1、ios实战开发之仿新浪微博(第一讲:新特性展示)
2、ios实战开发之仿新浪微博(第二讲:主框架搭建)
3、ios实战开发之仿新浪微博(第三讲:更多界面搭建)
4、ios实战开发之仿新浪微博(第四讲:OAuth认证)
5、ios实战开发之仿新浪微博(第五讲:微博数据加载)
6、ios实战开发之仿新浪微博(第六讲:微博数据展示一)
7、ios实战开发之仿新浪微博(第七讲:微博数据展示二)
8、ios实战开发之仿新浪微博(第八讲:微博数据展示三)
9、ios实战开发之仿新浪微博(第九讲:微博功能完善一)
10、ios实战开发之仿新浪微博(第十讲:微博功能完善二)
11、ios实战开发之仿新浪微博(第十一讲:微博功能完善三)
12、ios实战开发之仿新浪微博(小龙虾发布版)
|