- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
self.window.rootViewController = [[UINavigationController alloc]initWithRootViewController:[PersonListViewController new]];
//nonatomic / atomic / readonly / readwrite /getter / setter / assign / retain / copy / strong / weak /unsafe_unretained / notnull /null
//内部实现
//为什么?--面试知识点
/*
#pragma mark 引入,替换上面的PersonListViewController
MyTableViewController *myTVC = [[MyTableViewController alloc]initWithStyle:UITableViewStyleGrouped];
self.window.rootViewController = [[UINavigationController alloc]initWithRootViewController:myTVC];
*/
/*
//第一步:
创建PersonListViewController继承自UIController
创建PersonListView 继承自 UIView
//第二步:
在AppDelegate中,设置根视图控制器为导航控制器,并初始化PersonListViewController为导航控制器的根视图控制器
self.window.rootViewCOntroller = [[UINavigation alloc]initWithViewController:[PersonListViewController new]];
//第三步:
在PersonListViewController中用自定义视图替换自带的视图
在PersonView中声明UITableView对象,重写初始化方法,加载tableView
//第四步:
在PersonListViewController中的viewDidLoad中处理
1.设置导航栏上的Title,rightBarButtonItem
2.设置delegate和dataSource,遵循相应的协议并实现协议方法。
3.根据协议方法把tableView的外观做出来
4.加载数据
5.command+N 新建一个Person类继承自NSObject
6.在Person类中声明相应的属性,自定义初始化方法和便利构造器。
7.在PersonlistViewController.m中引入,写一个加载数据的模块loadData,并在viewDidLoad方法中使用。
8.注意:在使用过程中,需要使用到NSMutableDictionary,是因为需要使用到可变数组的互异性来存储对象。
----- 编辑 步骤 -----------
1.设置编辑状态,是否允许编辑
-(BOOL)tableView:canEditRowAtIndexPath:
2.设置编辑模式,加、减、可选状态、none-表示有可编辑的状态,但是没有编辑的能力。
-(UITableViewCellEditingStyle)tableView:
editingStyleForRowAtIndexPath:
3.处理编程过程。
-(void)tableView: commitEditingStyle: forRowAtIndexPath:
----- 移动 步骤 ----------
1.设置编辑状态,是否允许移动,省略。
2.设置移动模式,省略。
3.处理移动过程。
-(void)tableView: moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
---- 温故知新 ------------
1.-(UITableViewCell *)tableView: cellForRowAtIndexPath:(NSIndexPath *)indexPath
设置UITableViewCell中cell的内容中用到的重用机制:--重用池的概念---
0.在PersonListViewController.m的延展中声明私有属性cell
a.声明重用标识符-static cellID
b.从重用池中查找cellID
c.判断,如果不存在,就创建新的
d.使用,给textLable.text或者其他属性赋值
e.返回cell
---- 接触的新知识点 ----------
1.懒加载--重写getter方法,不使用的时候不创建,只有当使用的时候才创建。
系统中的例子就是:UITableViewCell中的textLable,imageView,和detailTitle
---- 接触的第二个新知识 ----------
1.处理编辑过程中
要注意的一点就是,在更新页面的过程中一定要记得更新内部数据。
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
2.处理移动过程中
也是要注意的一点就是。页面的更新一定要伴随着内部数据的更新。
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
移动:最重要的一点就是,移动并不是两个数据元素交换位置。
而是,先删除这个元素,然后再把元素插入到指定位置。
*/
return YES;
}
========================================
@interface PersonListViewController ()<UITableViewDataSource,UITableViewDelegate>
@property(nonatomic,strong) PersonListView *personList;
@property(nonatomic,strong) UITableViewCell *cell ;
//放数据.
@property(nonatomic,strong) NSMutableDictionary *allDictionary;
@end
@implementation PersonListViewController
-(void)loadView
{
self.personList = [[PersonListView alloc]initWithFrame:[UIScreen mainScreen].bounds];
self.view = self.personList;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"联系人";
//进入编辑状态 退出编辑状态
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editAction:)];
//数据源
self.personList.personListTV.dataSource = self;
self.personList.personListTV.delegate = self;
//模块
[self loadData];
}
//实现编辑按钮的响应事件
-(void)editAction:(UIBarButtonItem *)sender
{
if (self.personList.personListTV.editing == YES) {
sender.title = @"edit";
}else
{
sender.title = @"done";
}
//设置取反状态
[self.personList.personListTV setEditing:!self.personList.personListTV.editing animated:YES];
}
//加载数据
-(void)loadData
{
//懒加载:只有当我使用的时候才创建,不用的时候不创建。
//数据
Person *p1 = [Person personWithName:@"shuang"
Phone:@"138383839438"
Age:@"18"];
Person *p2 = [Person personWithName:@"xiao ming"
Phone:@"13838389438"
Age:@"6"];
Person *p3 = [Person personWithName:@"xiao miao zi"
Phone:@"110119120114"
Age:@"28"];
Person *p4 = [Person personWithName:@"xiao qiang"
Phone:@"12367890"
Age:@"12"];
Person *p5 = [Person personWithName:@"shuang qiang"
Phone:@"09876543212345678"
Age:@"17"];
Person *p6 = [Person personWithName:@"wang yan hua"
Phone:@"15154298103"
Age:@"12"];
//把联系人添加到可变数组中
NSMutableArray *arrayS = [NSMutableArray arrayWithObjects:p1,p5, nil];
NSMutableArray *arrayX = [NSMutableArray arrayWithObjects:p2,p3,p4, nil];
NSMutableArray *arrayW = [NSMutableArray arrayWithObjects:p6, nil];
[self.allDictionary setObject:arrayS forKey:@"S"];
[self.allDictionary setObject:arrayX forKey:@"X"];
[self.allDictionary setObject:arrayW forKey:@"W"];
}
//必须实现的
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//为什么点不出来呢?
return [[self.allDictionary objectForKey:self.allDictionary.allKeys[section]] count];
//也是可以的。
// return [self.allDictionary[self.allDictionary.allKeys[section]] count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//重用机制
//只初始化一次static
//0.声明重用标识符
static NSString *cellID = @"cellID";
//1.从重用队列中查找cell
_cell = [tableView dequeueReusableCellWithIdentifier:cellID];
//2.如果不存在,则创建新的
if (_cell == nil) {
self.cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
}
//3.使用
_cell.textLabel.text = @"A";
NSString *key = self.allDictionary.allKeys[indexPath.section];
NSArray *array = self.allDictionary[key];
Person *p = array[indexPath.row];
_cell.textLabel.text = p.name;
_cell.detailTextLabel.text = p.phone;
//右边的附加
_cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
//4.返回
return _cell;
}
//设置组标题。
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
//返回键值。
return self.allDictionary.allKeys[section];
}
//快速索引
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
//根据键值设置的。
return self.allDictionary.allKeys;
}
//可选的方法。
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.allDictionary.allKeys.count;
}
//处理内存警告的。
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark 设置是否编辑
//设置哪些行允许编辑
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
//默认情况下,所有行都可以编辑
//当有特殊情况时,进行判断,然后返回YES代表可以编辑,返回NO,代表,不可以编辑
return YES;
}
//设置编辑样式
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
//进行判断并返回相应的删除模式
return UITableViewCellEditingStyleDelete;
//可选
// return UITableViewCellEditingStyleDelete | UITableViewCellEditingStyleInsert;
}
//处理编辑过程
//==提交编辑
//只要实现这个方法,就可以直接滑动删除。
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
//更新数据
//1.获取key值
NSString *key = self.allDictionary.allKeys[indexPath.section];
//获取所有的value值
NSMutableArray *arrayValues = [self.allDictionary objectForKey:key];
//根据indexPath.row从value值中删除指定元素
[arrayValues removeObjectAtIndex:indexPath.row];
//更新页面(屏幕)
//可以同时删除很多行
// tableView deleteRowsAtIndexPaths:(NSArray *) withRowAnimation:(UITableViewRowAnimation)
//2.更新页面 动画性的删除在indexPaths:指定下标(几组几行的那一行)。
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
//===》第一种
if (arrayValues.count == 0) {
//更行数据
//从数组中移除指定的key。
[self.allDictionary removeObjectForKey:key];
//更新页面
//是一个类,组数的
NSIndexSet *set = [NSIndexSet indexSetWithIndex:indexPath.section];
[tableView deleteSections:set withRowAnimation:UITableViewRowAnimationAutomatic];
}
*/
//第二种--逼格高一点的.
//1.获取key 值
NSString *key = self.allDictionary.allKeys[indexPath.section];
//2.获取数组
NSMutableArray *mutableArray = [self.allDictionary objectForKey:key];
//获取元素
Person *person = mutableArray[indexPath.row];
//3.
if (mutableArray.count == 1) {
//更新数据
//如果数据只剩下了一个,只需要把一整组删除就可以了。
[self.allDictionary removeObjectForKey:key];
//更新页面
//获取哪一个分区
NSIndexSet *set = [NSIndexSet indexSetWithIndex:indexPath.section];
//直接删除哪一个分区
[tableView deleteSections:set withRowAnimation:UITableViewRowAnimationAutomatic];
}
else
{
//更新数据
//直接把他从数组中移除
[mutableArray removeObject:person];
//更新页面
//直接删除那一行,也可以删除多行
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
//1.进入编辑状态
//2.告诉Tableview 哪些行可以编辑,哪些不可以,默认是都可以编辑。可省略。
//3.设置编辑的样式。默认减号。可省略。
//4.处理编辑过程
//移动:
//1.进入编辑状态
//2.设置样式
//3.移动完成,处理移动过程。
}
#pragma mark 设置是否可以移动
//
//-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
//{
//
// return YES;
//
//}
#pragma mark 处理移动过程
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
//不能光在页面上移动,一定要注意内部数据也要进行处理
//更新数据---先删除,再插入
//======写的就是本组内。
//1.获取key
NSString *key = self.allDictionary.allKeys[sourceIndexPath.section];
//2.获取数组
NSMutableArray *mutableArray = [self.allDictionary objectForKey:key];
//3.获取元素
Person *person = mutableArray[sourceIndexPath.row];
//4.先删除
[mutableArray removeObject:person];
//5.再插入
[mutableArray insertObject:person atIndex:destinationIndexPath.row];
//移动的处理,可以不更新页面。因为OC帮我们写了更新页面的方法。
}
#pragma mark 设置禁止跨分区移动
-(NSIndexPath*)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
//如果原来的分区和目标的分区相同,返回目标的位置。
if (sourceIndexPath.section == proposedDestinationIndexPath.section) {
return proposedDestinationIndexPath;
}
else
{
//否则返回原来的位置,不允许用户这样移动。
return sourceIndexPath;
}
}
#pragma mark 懒加载:系统中第一次遇到的三个就是昨天的cell的textLable,ImageView和子标题。
//重写了getter方法
-(NSMutableDictionary *)allDictionary
{
if (_allDictionary == nil) {
self.allDictionary = [NSMutableDictionary dictionary];
}
//必须用下划线:self.allDictionary 的话,就又要走getter方法,这样会递归。
return _allDictionary;
}