源代码:
链接:
链接:
https://pan.baidu.com/s/1KgLCWEps3pMJnIzm1ZArpg 密码:h16b
主要代码:
//
// ViewController.m
// QQ列表
//
// Created by 许磊 on 2019/3/1.
// Copyright © 2019年 xulei. All rights reserved.
//
#import "ViewController.h"
#import "GroupModel.h"
#import "FriendModel.h"
#import "MJExtension.h"
#import "FriendTableViewCell.h"
#import "HeaderInSection.h"
@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>
/**保存所有小组的信息*/
@property (nonatomic,strong) NSMutableArray *groupModelsArray;
/**UITableView的属性变量*/
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%@",self.groupModelsArray);
}
#pragma mark -------lazyLoad ---------
//groupModelsArray的get方法 懒加载
-(void)manualLoad{
//获取plist文件路径
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"qq" ofType:@"plist"];
//读取文件的内容
NSArray *dataArray = [NSArray arrayWithContentsOfFile:filePath];
//解析数据
self.groupModelsArray = [NSMutableArray array];
for (NSDictionary *gDic in dataArray) {
//创建Group模型
GroupModel *model = [GroupModel modelWithDic:gDic];
//保存这个小组模型
[self.groupModelsArray addObject:model];
}
}
-(void)autoLoad{
//使用开开源库解决
[GroupModel mj_setupObjectClassInArray:^NSDictionary *{
return @{
@"friends":[FriendModel class],
};
}];
self.groupModelsArray = [GroupModel mj_objectArrayWithFilename:@"qq.plist"];
}
-(NSMutableArray *)groupModelsArray{
if (_groupModelsArray == nil) {
//手动
//[self manualLoad];
//自动
[self autoLoad];
}
return _groupModelsArray;
}
#pragma mark -------tableView配置 ---------
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
//配置TableView显示多少组数据
return self.groupModelsArray.count;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
//配置每个组有多少行数据
GroupModel *gModel = [self.groupModelsArray objectAtIndex:section];
if (gModel.status == kGroupStatusOpen) {
return gModel.friends.count;
} else{
return 0;
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//配置每行数据内容
static NSString *cellID = @"cellID";
FriendTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
//获取section对应的row的内容
//1.获取小组信息
GroupModel *gModel = [self.groupModelsArray objectAtIndex:indexPath.section];
//2.获取小组里面row对应的好友信息
FriendModel *fModel = [gModel.friends objectAtIndex:indexPath.row];
//3.配置cell
cell.iconImageView.image = [UIImage imageNamed:fModel.icon];
cell.nameLabel.text = fModel.name;
cell.modeLabel.text = fModel.mode;
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
//配置每行数据的高度
return 80;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
//配置每一个小组的头部内容
HeaderInSection *hView = [[[NSBundle mainBundle] loadNibNamed:@"HeaderInSection" owner:nil options:nil] firstObject];
GroupModel *gModel = [self.groupModelsArray objectAtIndex:section];
//设置小组的标题
hView.nameLabel.text = gModel.sectionName;
//判断当前这个箭头的方向
if (gModel.status == kGroupStatusClose) {
hView.arrowImageView.transform = CGAffineTransformRotate(hView.arrowImageView.transform, -M_PI_2);
}
//解决block循环引用
__block typeof(hView) weakSelf = hView;
//接受按钮被点击的事件
[hView setClickedBlock:^{
CGFloat angle;
//点击之后的事情
if (gModel.status == kGroupStatusOpen) {
//逆时针旋转90度
angle = -M_PI_2;
gModel.status = kGroupStatusClose;
} else{
//顺时针旋转90度
angle = M_PI_2;
gModel.status = kGroupStatusOpen;
}
//用更新之后的model去替换原来的model,其status属性改变了
[self.groupModelsArray replaceObjectAtIndex:section withObject:gModel];
//刷新section对应的小组
NSIndexSet *set = [NSIndexSet indexSetWithIndex:section];
[self.tableView reloadSections:set withRowAnimation:UITableViewRowAnimationFade];
//动画
[UIView animateWithDuration:0.25 animations:^{
weakSelf.arrowImageView.transform = CGAffineTransformRotate(weakSelf.arrowImageView.transform, angle);
}];
}];
return hView;
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
//配置头部视图高度
return 40;
}
@end
//
// GroupModel.h
// QQ列表
//
// Created by 许磊 on 2019/3/1.
// Copyright © 2019年 xulei. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef enum {
kGroupStatusClose,
kGroupStatusOpen
}kGroupStatus;
@interface GroupModel : NSObject
//能被外界访问的数据
/**组名*/
@property (nonatomic,copy) NSString *sectionName;
/**好友模型数组-手动*/
@property (nonatomic,strong) NSArray *friendModelsArray;
/**好友模型数组-自动*/
@property (nonatomic,strong) NSArray *friends;
/**记录小组的状态*/
@property (nonatomic,assign) kGroupStatus status;
//数据解析
+(instancetype)modelWithDic:(NSDictionary *)dic;
@end
//
// GroupModel.m
// QQ列表
//
// Created by 许磊 on 2019/3/1.
// Copyright © 2019年 xulei. All rights reserved.
//
#import "GroupModel.h"
#import "FriendModel.h"
@implementation GroupModel
//数据解析
+(instancetype)modelWithDic:(NSDictionary *)dic{
//创建GroupModel
GroupModel *model = [[GroupModel alloc] init];
model.sectionName = [dic objectForKey:@"sectionName"];
//创建好友的模型数组 外部需要不可变的 用可变的暂时数组代替
NSMutableArray *tempArray = [NSMutableArray array];
//获取好友信息
NSArray *friends = [dic objectForKey:@"friends"];
//一个一个地解析好友数据
for (NSDictionary *fDic in friends) {
//创建好友的模型对象
FriendModel *fModel = [FriendModel new];
[fModel setValuesForKeysWithDictionary:fDic];
//保存这个模型 --- 添加到数组中
[tempArray addObject:fModel];
}
//将暂时的数组赋给好友的模型数组
model.friendModelsArray = tempArray;
return model;
}
@end
//
// FriendModel.h
// QQ列表
//
// Created by 许磊 on 2019/3/1.
// Copyright © 2019年 xulei. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface FriendModel : NSObject
//能被外界访问的数据
/**头像*/
@property (nonatomic,copy) NSString *icon;
/**名称*/
@property (nonatomic,copy) NSString *name;
/**动态*/
@property (nonatomic,copy) NSString *mode;
@end
//
// FriendModel.m
// QQ列表
//
// Created by 许磊 on 2019/3/1.
// Copyright © 2019年 xulei. All rights reserved.
//
#import "FriendModel.h"
@implementation FriendModel
@end
//
// FriendTableViewCell.h
// QQ列表
//
// Created by 许磊 on 2019/3/2.
// Copyright © 2019年 xulei. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface FriendTableViewCell : UITableViewCell
/**cell显示的头像图片*/
@property (weak, nonatomic) IBOutlet UIImageView *iconImageView;
/**cell上显示的名字*/
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
/**cell上显示的动态内容*/
@property (weak, nonatomic) IBOutlet UILabel *modeLabel;
@end
//
// FriendTableViewCell.m
// QQ列表
//
// Created by 许磊 on 2019/3/2.
// Copyright © 2019年 xulei. All rights reserved.
//
#import "FriendTableViewCell.h"
@implementation FriendTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
//
// HeaderInSection.h
// QQ列表
//
// Created by 许磊 on 2019/3/2.
// Copyright © 2019年 xulei. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef void (^headerButtonClicked)(void);
@interface HeaderInSection : UIView
/**旋转视图*/
@property (weak, nonatomic) IBOutlet UIImageView *arrowImageView;
/**组名*/
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
/**定义一个block属性变量*/
@property (nonatomic,copy) headerButtonClicked clickedBlock;;
@end
//
// HeaderInSection.m
// QQ列表
//
// Created by 许磊 on 2019/3/2.
// Copyright © 2019年 xulei. All rights reserved.
//
#import "HeaderInSection.h"
@implementation HeaderInSection
- (IBAction)headerButtonDidClicked:(UIButton *)sender {
//回调按钮被点击的事件
self.clickedBlock();
}
@end
运行结果
运行结果开发步骤
1.处理数据转模型
2.自定义Cell
3.sectionheader视图
附一:UITableView
-
1.UITableView数据的显示通过Delegate和DataSource来配置(NSIndexPath:section row)
-
2.UITableView的类型 plain和grouped类型
-
3.UITableView的重复利用机制
-
4.UITableViewCell的类型 Default value1 value2 subtitle
-
5.自己创建UITableViewCell
a.在创建cell的同时手动添加控件 使用tag来获取这个控件
b.创建一个类继承于UITableViewCell封装Cell的布局
c.xib自定义Cell
d.storyboard自定义Cell,前提是控制器在storyboard里面 -
6.UITableView刷新数据
a.使用数组保存资源
b.reloadData -
7.数据封装为一个模型
a. 用一个类来描述一条数据
b. 访问方便 减少代码的冗余
附二:@property 属性类型归纳和介绍
1.atomic:原子操作 给资源加锁解锁 安全 效率不高
2.nonatomic:非原子操作 没有加锁解锁机制 不安全 效率高
3.strong:强引用 声明对不是自己创建的对象的拥有权 reatinCount+1 OC的对象类型就用它 针对 @property
4.retain:和strong相同,除了@property 关键字以外,在代码里面也需要声明拥有权 reatinCount+1
5.copy:拷贝一份 不是所有的对象类型都可以使用 自己创建的对象必须服从NSCopy协议才能使用 修饰NSString和block一般只用copy
6.弱引用: 只是定义了某一个类型的对象 不会对这个对象声明拥有权(不引用)
7.readwrite:可读可写(默认) 提供了set,get方法
8.readonly:只读 只提供get方法
9.assign:修饰C语言的基本数据类型 为了防止循环引用delegate
1.atomic与nonatomic
atomic:默认是有该属性的,这个属性是为了保证程序在多线程情况,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题
nonatomic:如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率。2.readwrite与readonly(readwrite、readonly这两个属性的真正价值,不是提供成员变量访问接口,而是控制成员变量的访问权限)
readwrite:这个属性是默认的情况,会自动为你生成存取器。
readonly:只生成getter不会有setter方法。3.strong与weak(strong与retain功能相似;weak与assign相似,只是当对象消失后weak会自动把指针变为nil;)
strong:强引用,也是我们通常说的引用,其存亡直接决定了所指向对象的存亡。如果不存在指向一个对象的引用,并且此对象不再显示在列表中,则此对象会被从内存中释放。
weak:弱引用,不决定对象的存亡。即使一个对象被持有无数个弱引用,只要没有强引用指向它,那么还是会被清除。4.assign、copy、retain
assign:默认类型,setter方法直接赋值,不进行任何retain操作,不改变引用计数。一般用来处理基本数据类型。
retain:释放旧的对象(release),将旧对象的值赋给新对象,再令新对象引用计数为1。我理解为指针的拷贝,拷贝一份原来的指针,释放原来指针指向的对象的内容,再令指针指向新的对象内容。
copy:与retain处理流程一样,先对旧值release,再copy出新的对象,retainCount为1.为了减少对上下文的依赖而引入的机 制。我理解为内容的拷贝,向内存申请一块空间,把原来的对象内容赋给它,令其引用计数为1。对copy属性要特别注意:被定义有copy属性的对象必须要 符合NSCopying协议,必须实现- (id)copyWithZone:(NSZone *)zone方法。
也可以直接使用:
使用assign: 对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等)
使用copy: 对NSString
使用retain: 对其他NSObject和其子类
网友评论