效果图
自定义View是一项非常有成就感的实践,如果有Android基础的同学接触起来应该会比较顺手,基本思路都差不多。项目采用原生的布局方式,实现仿微信消息列表效果,主要是学习自定义Cell,展示头像、标题、消息概要、时间和未读数View。下图左边是样例,右边是实现的效果图。
项目结构
项目采用MVC模式,Model处理数据,View提供自定义的Cell和Cell的位置大小,ViewController负责获取数据、创建View和实现UITableView的代理和数据源方法,结构如图所示。
数据源
MsgModel是消息的数据源,包括头像、标题、消息概要、时间和未读数。DataManager负责解析本地的json文件并封装数据,对消息列表数据增删改查操作。
#import "DataManager.h"
#import "MsgModel.h"
#import "MessageItemFrame.h"
@implementation DataManager
- (NSMutableArray *)onParseJson
{
NSString *jsonStr = nil;
NSMutableArray *dataArr = nil;
//获取项目json文件路径
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"msgdatas" ofType:@"json"];
NSFileManager *fileMgr = [NSFileManager defaultManager];
// NSError *error;
if ([fileMgr fileExistsAtPath:filePath]) {
//可以通过流的形式解析
NSInputStream *is = [[NSInputStream alloc] initWithFileAtPath:filePath];
[is open];
id jsonObj = [NSJSONSerialization JSONObjectWithStream:is options:NSJSONReadingAllowFragments error:nil];
[is close];
if ([jsonObj isKindOfClass:[NSArray class]]) {
dataArr = [[NSMutableArray alloc] init];
for (NSDictionary *dict in (NSArray *) jsonObj) {
MsgModel *model = [[MsgModel alloc] init];
model.msgId = [dict objectForKey:@"_id"];
model.pic = [dict objectForKey:@"picture"];
model.name = [dict objectForKey:@"name"];
model.msg = [dict objectForKey:@"message"];
model.time = [dict objectForKey:@"time"];
model.unreadCount = [(NSNumber *) [dict objectForKey:@"unreadCount"] integerValue];
MessageItemFrame *itemFrame = [[MessageItemFrame alloc] init];
itemFrame.msgModel = model;
[dataArr addObject:itemFrame];
}
}
} else {
NSLog(@"文件不存在!");
return nil;
}
return dataArr;
}
@end
考虑到刚刚接触ISO学习的同学对于Json解析还不是很熟悉,所以补充一下Json解析方法,需要根据不同的数据结构进行解析,核心是通过苹果提供的NSJSONSerialization解析,例如数据是NSDictionary格式:
NSString *jsonArr = @"[{\"_id\":\"5d1edda6710720fb68360a89\",\"name\":\"Daisy Pugh\"},{\"_id\":\"5d1edda6710720fb68360a89\",\"name\":\"DaisyPugh\"}]";
NSData *jsonData = [jsonArr dataUsingEncoding:NSUTF8StringEncoding];
id jsonObj = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingAllowFragments error:nil];
if ([jsonObj isKindOfClass:[NSDictionary class]])
{
NSDictionary *dict = (NSDictionary *) jsonObj;
NSString *_id = [dict objectForKey:@"_id"];
NSString *_pic = [dict objectForKey:@"picture"];
NSLog(@"id: %@ picture: %@", _id, _pic);
}
解析JSON文件有很多种方式,下面主要介绍三种:
第一种根据规范的字符串格式:
jsonStr = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSData *jsonData = [jsonStr dataUsingEncoding:NSUTF8StringEncoding];
id jsonObj = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:nil];
第二种是通过直接NSData的initWithContentsOfFile解析文件:
NSData *jsonData = [[NSData alloc] initWithContentsOfFile:filePath];
id jsonObj = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:nil];
第三种是流的形式解析文件:
NSInputStream *is = [[NSInputStream alloc] initWithFileAtPath:filePath];