第四天
微博数据展示:获取服务器数据,json数据的解析,MVC的使用,自定义cell高度的计算,一些分类的设计。已经是第四天了,虽然每天都有课程,但这个东西也基本完成了一大半吧,一些忘掉的知识也捡起来了。看了一下第一次写的笔记,做到这个程度可是花了将近十多天的时间,这次这么短的时间就做到了着,还是有一点复制粘贴的成分,但是大致的思维过程还是有的,也练了一下编码速度的。四天时间主要就是回顾一下之前做的一些事情,下一步不打算接着做下去了,要将第一次没完成的很多细节完善,争取做得更加完美。简单的记录下今天吧,很多课上的很没意思的说。
1.很明显需要自定义cell,而微博展示这种比较复杂的cell,我们在一开始就把所有要用到的控件加进去,然后再根据数据选择是否进行显示。
2.首先是要在home模块中向新浪请求数据,[self loadStatus],方法中我们需要使用账号的access_token作为请求参数,通过SVAccountTool工具类很容易得到。
- (void)loadStatus
{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; NSMutableDictionary *pramas = [NSMutableDictionary dictionary];
// 拿到当前账号
SVAccount *account = [SVAccountTool account];
pramas[@"access_token"] = account.access_token; [manager GET:@"https://api.weibo.com/2/statuses/home_timeline.json" parameters:pramas progress:^(NSProgress * _Nonnull uploadProgress) { } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
// 将字典数组转为模型数组(里面放的就是IWStatus模型)
NSArray *statusArray = [SVStatus mj_objectArrayWithKeyValuesArray:responseObject[@"statuses"]];
// 创建frame模型对象
NSMutableArray *statusFrameArray = [NSMutableArray array];
for (SVStatus *status in statusArray) {
SVStatusFrame *statusFrame = [[SVStatusFrame alloc] init];
// 传递微博模型数据
statusFrame.status = status;
[statusFrameArray addObject:statusFrame];
}
// 赋值
self.statusFrames = statusFrameArray;
// 刷新表格
[self.tableView reloadData];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"status error--%@", error);
}];
}
3.在请求数据后,服务器会返回json数据,为了面向模型开发,添加SVStatus模型和SVUser模型,并根据新浪返回数据和我们需要的数据为其添加成员变量。(在这里第一次的时候是先进行了数据解析,直接在系统的cell上展示了头像、用户名等数据,这次做就直接自定义cell)
#import <Foundation/Foundation.h>
@class SVUser;
@interface SVStatus : NSObject
/**
* 微博创建时间
*/
@property (nonatomic, copy) NSString *created_at;
/**
* 微博ID
*/
@property (nonatomic, copy) NSString *ID;
/**
* 微博内容
*/
@property (nonatomic, copy) NSString *text;
/**
* 微博来源
*/
@property (nonatomic, copy) NSString *source;
/**
* 微博配图的缩略图地址
*/
@property (nonatomic, copy) NSString *thumbnail_pic;
/**
* 转发数
*/
@property (nonatomic, assign) int retwweted_count;
/**
* 评论数
*/
@property (nonatomic, assign) int reposts_count;
/**
* 点赞数
*/
@property (nonatomic, assign) int attitudes_count;
/**
* 发微博的人
*/
@property (nonatomic, strong) SVUser *user;
/**
* 转发的微博
*/
@property (nonatomic, strong) SVStatus *retweeted_status;
@end
#import <Foundation/Foundation.h> @interface SVUser : NSObject
/**
* 用户的ID
*/
@property (nonatomic, copy) NSString *idstr;
/**
* 用户的昵称
*/
@property (nonatomic, copy) NSString *name;
/**
* 用户的头像
*/
@property (nonatomic, copy) NSString *profile_image_url; /**
* 会员等级
*/
@property (nonatomic, assign) int mbrank;
/**
* 会员类型
*/
@property (nonatomic, assign) int mbtype;
@end
4.典型的cell高度不确定时,分析微博的结构,而微博的结构根据内容会有所不同,基本为三种:只有文字、文字和配图、带有转发的微博。不管哪种,按照从上到下的顺序,就可以将其分为三个部分:头像昵称、主要内容和转评赞条。为了确定位置,会再添加一个计算frame的模型SVStatusFrame,用来计算每一个控件在整个cell的位置。在SVStatusFrame中只需要重写status的setter方法,在给status设置值得时候,根据不同的值进行计算控件的frame,最后得出整个cell的高度。目前在SVStatusFrame的.h文件中哟很多关于字体、颜色的宏定义,还有目前对于头文件的引用也不是很规范,在基本效果完成之后会将他们进行抽取。
@interface SVStatusFrame : NSObject
@property (nonatomic, strong) SVStatus *status; /** 顶部的view */
@property (nonatomic, assign, readonly) CGRect topViewF;
/** 头像 */
@property (nonatomic, assign, readonly) CGRect iconViewF;
/** 会员图标 */
@property (nonatomic, assign, readonly) CGRect vipViewF;
/** 配图 */
@property (nonatomic, assign, readonly) CGRect photoViewF;
/** 昵称 */
@property (nonatomic, assign, readonly) CGRect nameLabelF;
/** 时间 */
@property (nonatomic, assign, readonly) CGRect timeLabelF;
/** 来源 */
@property (nonatomic, assign, readonly) CGRect sourceLabelF;
/** 正文\内容 */
@property (nonatomic, assign, readonly) CGRect contentLabelF; /** 被转发微博的view(父控件) */
@property (nonatomic, assign, readonly) CGRect retweetViewF;
/** 被转发微博作者的昵称 */
@property (nonatomic, assign, readonly) CGRect retweetNameLabelF;
/** 被转发微博的正文\内容 */
@property (nonatomic, assign, readonly) CGRect retweetContentLabelF;
/** 被转发微博的配图 */
@property (nonatomic, assign, readonly) CGRect retweetPhotoViewF; /** 微博的工具条 */
@property (nonatomic, assign, readonly) CGRect statusToolbarF; /** cell的高度 */
@property (nonatomic, assign, readonly) CGFloat cellHeight;
5.为了使cell不过于依赖控制器而存在,为其提供一个类方法来创建件cell,并在cell内部实现重用。在该方法中添加控件,添加控件分成了3个部分,其中的代码很简单的就是创建控件、设置只要不需改变的值、添加、保存起来。
// 全部的控件
@interface SVStatusCell()
/** 顶部的view */
@property (nonatomic, weak) UIImageView *topView;
/** 头像 */
@property (nonatomic, weak) UIImageView *iconView;
/** 会员图标 */
@property (nonatomic, weak) UIImageView *vipView;
/** 配图 */
@property (nonatomic, weak) UIImageView *photoView;
/** 昵称 */
@property (nonatomic, weak) UILabel *nameLabel;
/** 时间 */
@property (nonatomic, weak) UILabel *timeLabel;
/** 来源 */
@property (nonatomic, weak) UILabel *sourceLabel;
/** 正文\内容 */
@property (nonatomic, weak) UILabel *contentLabel; /** 被转发微博的view(父控件) */
@property (nonatomic, weak) UIImageView *retweetView;
/** 被转发微博作者的昵称 */
@property (nonatomic, weak) UILabel *retweetNameLabel;
/** 被转发微博的正文\内容 */
@property (nonatomic, weak) UILabel *retweetContentLabel;
/** 被转发微博的配图 */
@property (nonatomic, weak) UIImageView *retweetPhotoView; /** 微博的工具条 */
@property (nonatomic, weak) UIImageView *statusToolbar;
@end
+ (instancetype)cellWithtableView:(UITableView *)tableView
{
static NSString *ID = @"status";
SVStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[SVStatusCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
return cell;
} - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// 1.添加原创微博内部的子控件
[self setupOriginalSubviews]; // 2.添加被转发微博内部的子控件
[self setupRetweetSubviews]; // 3.添加微博的工具条
[self setupStatusToolBar];
}
return self;
}
6.对于给cell上的控件赋值数据同样很简单,就是重写statusFrame的setter方法,再给他赋值的同时,将status数据传递过来。
/**
* 传递模型数据
*/
- (void)setStatusFrame:(SVStatusFrame *)statusFrame
{
_statusFrame = statusFrame; // 1.原创微博
[self setupOriginalData]; // 2.被转发微博
[self setupRetweetData]; // 3.微博工具条
[self setupStatusToolbar];
}