一个实现了添加 删除功能的iOS通讯录:
AppDelegate.m : (引入RootViewController.h文件)
//创建根视图控制器
RootViewController
*rootVC = [[
RootViewController
alloc
]
init
];
UINavigationController *navVC = [[ UINavigationController alloc ] initWithRootViewController :rootVC];
UINavigationController *navVC = [[ UINavigationController alloc ] initWithRootViewController :rootVC];
self.window.rootViewController = navVC;
RootViewController.h :
//遵守如下两个协议
@interface
RootViewController :
UIViewController
<
UITableViewDataSource
,
UITableViewDelegate
>
@end
RootViewController.m :
//引入两个头件并定义如下属性
#import "Student.h"
#import "DegaViewController.h"
@interface RootViewController ()
@property(nonatomic ,retain)NSMutableDictionary *dic;
@property(nonatomic ,retain)NSMutableArray *grouparr;
@property(nonatomic ,retain)UITableView *tableView;
@property(nonatomic ,assign)BOOL *b;
#import "DegaViewController.h"
@interface RootViewController ()
@property(nonatomic ,retain)NSMutableDictionary *dic;
@property(nonatomic ,retain)NSMutableArray *grouparr;
@property(nonatomic ,retain)UITableView *tableView;
@property(nonatomic ,assign)BOOL *b;
@end
//完成以下步骤
- (
id
)initWithNibName:(
NSString
*)nibNameOrNil bundle:(
NSBundle
*)nibBundleOrNil
{
self = [ super initWithNibName :nibNameOrNil bundle :nibBundleOrNil];
if ( self ) {
// 数据处理
//1. 路径
NSString *path = [[ NSBundle mainBundle ] pathForResource : @"Class25ContactList" ofType : @"plist" ];
//2. 最外层字典
_dic = [[ NSMutableDictionary alloc ] initWithContentsOfFile :path];
//3. 所有 key 值(分组名)
_grouparr = [[ NSMutableArray alloc ] initWithArray :[ _dic allKeys ]];
//4 。给所有分组名排序
[ _grouparr sortUsingSelector : @selector (compare:)];
UIBarButtonItem *barButton = [[ UIBarButtonItem alloc ] initWithTitle : @" 编辑 " style : UIBarButtonItemStylePlain target : self action : @selector (editTableView:)];
self . navigationItem . leftBarButtonItem = barButton;
// 添加按钮
// 系统为我们提供了编辑按钮,同时也提供了编辑方法,我们可以不用重写属性和方法
//controller 为我们提供了编辑方法(不需要我们重新添加方法)
self . navigationItem . rightBarButtonItem = self . editButtonItem ;
self . navigationItem . title = @" 联系人 " ;
{
self = [ super initWithNibName :nibNameOrNil bundle :nibBundleOrNil];
if ( self ) {
// 数据处理
//1. 路径
NSString *path = [[ NSBundle mainBundle ] pathForResource : @"Class25ContactList" ofType : @"plist" ];
//2. 最外层字典
_dic = [[ NSMutableDictionary alloc ] initWithContentsOfFile :path];
//3. 所有 key 值(分组名)
_grouparr = [[ NSMutableArray alloc ] initWithArray :[ _dic allKeys ]];
//4 。给所有分组名排序
[ _grouparr sortUsingSelector : @selector (compare:)];
UIBarButtonItem *barButton = [[ UIBarButtonItem alloc ] initWithTitle : @" 编辑 " style : UIBarButtonItemStylePlain target : self action : @selector (editTableView:)];
self . navigationItem . leftBarButtonItem = barButton;
// 添加按钮
// 系统为我们提供了编辑按钮,同时也提供了编辑方法,我们可以不用重写属性和方法
//controller 为我们提供了编辑方法(不需要我们重新添加方法)
self . navigationItem . rightBarButtonItem = self . editButtonItem ;
self . navigationItem . title = @" 联系人 " ;
}
return
self
;
}
- ( void )viewDidLoad
{
[ super viewDidLoad ];
_tableView = [[ UITableView alloc ] initWithFrame :[ UIScreen mainScreen ]. bounds style : UITableViewStylePlain ];
_tableView . delegate = self ;
_tableView . dataSource = self ;
[ self . view addSubview : _tableView ];
}
#pragma mark tableView 编辑
-( void )setEditing:( BOOL )editing animated:( BOOL )animated{
_b = NO ;
// 向父类发送消息
// 在 OC 中,重写父类的方法的时候,必须先向父类发送 super 消息,尤其是系统类
[ super setEditing :editing animated :animated];
//tableViewde 编辑状态设置
[ _tableView setEditing :editing animated :animated];
// 点击后更换的 title
self . navigationItem . rightBarButtonItem . title = editing? @"Done" : @" 添加 " ;
}
// 第一步
-( void )editTableView:( UIBarButtonItem *)barbutton{
_b = YES ;
// 当按钮显示完成时,我们点击应发生以下事情
//1.tableView 处于编辑状态
//2. 按钮显示完成
// 当按钮显示完成时,我们点击应发生一下事情
//1.tableView 处于非编辑状态
//2. 按钮显示为编辑
if ([barbutton. title isEqualToString : @" 删除 " ]) {
[ _tableView setEditing : YES animated : YES ];
barbutton. title = @"Done" ;
} else {
[ _tableView setEditing : NO animated : YES ];
barbutton. title = @" 删除 " ;
}
}
// 第二步 指定可编辑的东西
-( BOOL )tableView:( UITableView *)tableView canEditRowAtIndexPath:( NSIndexPath *)indexPath{
//
// if (indexPath.section == 1 && indexPath.row == 1) {
// return NO;
// }
return YES ; // 默认是 Yes;
}
// 第三步 指定编辑样式(默认返回的是删除)
-( UITableViewCellEditingStyle )tableView:( UITableView *)tableView editingStyleForRowAtIndexPath:( NSIndexPath *)indexPath{
if ( _b == NO ) {
return UITableViewCellEditingStyleInsert ;
}
return UITableViewCellEditingStyleDelete ;
}
// 第四步 完成编辑
-( void )tableView:( UITableView *)tableView commitEditingStyle:( UITableViewCellEditingStyle )editingStyle forRowAtIndexPath:( NSIndexPath *)indexPath{
if (editingStyle == UITableViewCellEditingStyleDelete ) {
#warning 切记:在进行删除操作的时候,一定要先删除数据,再删除 UI
// 先删除数据
NSMutableArray *arr = [ _dic objectForKey : _grouparr [indexPath. section ]];
// 如果当前只剩一个 row 的时候 直接删除 section
if (arr. count == 1 ) {
// 删除数据
[ _dic removeObjectForKey : _grouparr [indexPath. section ]];
[ _grouparr removeObjectAtIndex :indexPath. section ];
// 删除 ui
NSIndexSet *set = [ NSIndexSet indexSetWithIndex :indexPath. section ];
[ _tableView deleteSections :set withRowAnimation : UITableViewRowAnimationLeft ];
} else {
[arr removeObjectAtIndex :indexPath. row ];
// 再删除 Ui
[ _tableView deleteRowsAtIndexPaths : @[ indexPath ] withRowAnimation : UITableViewRowAnimationAutomatic ];
}
} else if (editingStyle == UITableViewCellEditingStyleInsert ){
#warning 切记:操作 UI 之前先操作数据
NSDictionary *dict = @{ @"name" : @" 杨玉伟 " , @"gender" : @" 男 " , @"age" : @"26" , @"phoneNumber" : @"13578456201" , @"hobby" : @"piupiu!!" , @"picture" : @"yuwei.png" } ;
// 找到对应的分区数组
NSMutableArray *arr = [ _dic objectForKey : _grouparr [indexPath. section ]];
// 添加
[arr insertObject :dict atIndex :indexPath. row + 1 ];
// 添加 UI
NSIndexPath *newindexPath = [ NSIndexPath indexPathForRow :indexPath. row + 1 inSection :indexPath. section ];
[ _tableView insertRowsAtIndexPaths : @[ newindexPath ] withRowAnimation : UITableViewRowAnimationAutomatic ];
}
}
#pragma mark tableView 基本布局
// 多少个分区
- ( NSInteger )numberOfSectionsInTableView:( UITableView *)tableView
{
return _grouparr . count ;
}
// 分区内有多少行
- ( NSInteger )tableView:( UITableView *)tableView numberOfRowsInSection:( NSInteger )section{
// 取出当前分区的分区标题
NSString *key = _grouparr [section];
// 取出当前分区的组成 row 的数据
NSArray *array = [ _dic objectForKey :key];
return array. count ;
}
//cell
- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath{
NSString *atr = @"hrthrt" ;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier :atr];
if (cell == nil ) {
cell = [[ UITableViewCell alloc ] initWithStyle : UITableViewCellStyleSubtitle reuseIdentifier :atr];
}
// 取出分组对应的数组(找到对应分区)
NSArray *array = [ _dic objectForKey : _grouparr [indexPath. section ]];
// 取出具体的字典(找到对应的行)
NSDictionary *dict = array[indexPath. row ];
Student *s = [ Student new ];
[s setValuesForKeysWithDictionary :dict];
//cell 上显示数据
cell. textLabel . text = s. name ;
cell. detailTextLabel . text = s. phoneNumber ;
cell. imageView . image = [ UIImage imageNamed : @"mx.png" ];
return cell;
}
// 分区标题
-( NSString *)tableView:( UITableView *)tableView titleForHeaderInSection:( NSInteger )section{
return _grouparr [section];
}
// 索引
-( NSArray *)sectionIndexTitlesForTableView:( UITableView *)tableView{
return _grouparr ;
}
#pragma mark 页面跳转
-( void )tableView:( UITableView *)tableView didSelectRowAtIndexPath:( NSIndexPath *)indexPath{
DegaViewController *detaPage = [ DegaViewController new ];
// 取出分组对应的数组(找到对应分区)
NSArray *array = [ _dic objectForKey : _grouparr [indexPath. section ]];
// 取出具体的字典(找到对应的行)
NSDictionary *dict = array[indexPath. row ];
// 完成 model 赋值
Student *s = [ Student new ];
[s setValuesForKeysWithDictionary :dict];
// 传值
detaPage. stu = s;
// 跳转
[ self . navigationController pushViewController :detaPage animated : YES ];
}
#pragma mark tableView 移动
// 处于编辑状态(其他按钮的方法)
// 能否移动
-( BOOL )tableView:( UITableView *)tableView canMoveRowAtIndexPath:( NSIndexPath *)indexPath{
return YES ;
}
// 移动完成
-( void )tableView:( UITableView *)tableView moveRowAtIndexPath:( NSIndexPath *)sourceIndexPath toIndexPath:( NSIndexPath *)destinationIndexPath{
// 获取移动的数据
NSMutableArray *array = [ _dic objectForKey : _grouparr [sourceIndexPath. section ]];
NSDictionary *dict = [array objectAtIndex :sourceIndexPath. row ];
// 删除源数据
[array removeObjectAtIndex :sourceIndexPath. row ];
// 添加到要移动的目的地
[array insertObject :dict atIndex :destinationIndexPath. row ];
}
// 是否支持移动
-( NSIndexPath *)tableView:( UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:( NSIndexPath *)sourceIndexPath toProposedIndexPath:( NSIndexPath *)proposedDestinationIndexPath{
// 如果在一个分区,我们就可以让它留在这个分区
if (sourceIndexPath. section == proposedDestinationIndexPath. section ) {
return proposedDestinationIndexPath;
}
// 否则,哪来的回哪去
return sourceIndexPath;
}
- ( void )viewDidLoad
{
[ super viewDidLoad ];
_tableView = [[ UITableView alloc ] initWithFrame :[ UIScreen mainScreen ]. bounds style : UITableViewStylePlain ];
_tableView . delegate = self ;
_tableView . dataSource = self ;
[ self . view addSubview : _tableView ];
}
#pragma mark tableView 编辑
-( void )setEditing:( BOOL )editing animated:( BOOL )animated{
_b = NO ;
// 向父类发送消息
// 在 OC 中,重写父类的方法的时候,必须先向父类发送 super 消息,尤其是系统类
[ super setEditing :editing animated :animated];
//tableViewde 编辑状态设置
[ _tableView setEditing :editing animated :animated];
// 点击后更换的 title
self . navigationItem . rightBarButtonItem . title = editing? @"Done" : @" 添加 " ;
}
// 第一步
-( void )editTableView:( UIBarButtonItem *)barbutton{
_b = YES ;
// 当按钮显示完成时,我们点击应发生以下事情
//1.tableView 处于编辑状态
//2. 按钮显示完成
// 当按钮显示完成时,我们点击应发生一下事情
//1.tableView 处于非编辑状态
//2. 按钮显示为编辑
if ([barbutton. title isEqualToString : @" 删除 " ]) {
[ _tableView setEditing : YES animated : YES ];
barbutton. title = @"Done" ;
} else {
[ _tableView setEditing : NO animated : YES ];
barbutton. title = @" 删除 " ;
}
}
// 第二步 指定可编辑的东西
-( BOOL )tableView:( UITableView *)tableView canEditRowAtIndexPath:( NSIndexPath *)indexPath{
//
// if (indexPath.section == 1 && indexPath.row == 1) {
// return NO;
// }
return YES ; // 默认是 Yes;
}
// 第三步 指定编辑样式(默认返回的是删除)
-( UITableViewCellEditingStyle )tableView:( UITableView *)tableView editingStyleForRowAtIndexPath:( NSIndexPath *)indexPath{
if ( _b == NO ) {
return UITableViewCellEditingStyleInsert ;
}
return UITableViewCellEditingStyleDelete ;
}
// 第四步 完成编辑
-( void )tableView:( UITableView *)tableView commitEditingStyle:( UITableViewCellEditingStyle )editingStyle forRowAtIndexPath:( NSIndexPath *)indexPath{
if (editingStyle == UITableViewCellEditingStyleDelete ) {
#warning 切记:在进行删除操作的时候,一定要先删除数据,再删除 UI
// 先删除数据
NSMutableArray *arr = [ _dic objectForKey : _grouparr [indexPath. section ]];
// 如果当前只剩一个 row 的时候 直接删除 section
if (arr. count == 1 ) {
// 删除数据
[ _dic removeObjectForKey : _grouparr [indexPath. section ]];
[ _grouparr removeObjectAtIndex :indexPath. section ];
// 删除 ui
NSIndexSet *set = [ NSIndexSet indexSetWithIndex :indexPath. section ];
[ _tableView deleteSections :set withRowAnimation : UITableViewRowAnimationLeft ];
} else {
[arr removeObjectAtIndex :indexPath. row ];
// 再删除 Ui
[ _tableView deleteRowsAtIndexPaths : @[ indexPath ] withRowAnimation : UITableViewRowAnimationAutomatic ];
}
} else if (editingStyle == UITableViewCellEditingStyleInsert ){
#warning 切记:操作 UI 之前先操作数据
NSDictionary *dict = @{ @"name" : @" 杨玉伟 " , @"gender" : @" 男 " , @"age" : @"26" , @"phoneNumber" : @"13578456201" , @"hobby" : @"piupiu!!" , @"picture" : @"yuwei.png" } ;
// 找到对应的分区数组
NSMutableArray *arr = [ _dic objectForKey : _grouparr [indexPath. section ]];
// 添加
[arr insertObject :dict atIndex :indexPath. row + 1 ];
// 添加 UI
NSIndexPath *newindexPath = [ NSIndexPath indexPathForRow :indexPath. row + 1 inSection :indexPath. section ];
[ _tableView insertRowsAtIndexPaths : @[ newindexPath ] withRowAnimation : UITableViewRowAnimationAutomatic ];
}
}
#pragma mark tableView 基本布局
// 多少个分区
- ( NSInteger )numberOfSectionsInTableView:( UITableView *)tableView
{
return _grouparr . count ;
}
// 分区内有多少行
- ( NSInteger )tableView:( UITableView *)tableView numberOfRowsInSection:( NSInteger )section{
// 取出当前分区的分区标题
NSString *key = _grouparr [section];
// 取出当前分区的组成 row 的数据
NSArray *array = [ _dic objectForKey :key];
return array. count ;
}
//cell
- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath{
NSString *atr = @"hrthrt" ;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier :atr];
if (cell == nil ) {
cell = [[ UITableViewCell alloc ] initWithStyle : UITableViewCellStyleSubtitle reuseIdentifier :atr];
}
// 取出分组对应的数组(找到对应分区)
NSArray *array = [ _dic objectForKey : _grouparr [indexPath. section ]];
// 取出具体的字典(找到对应的行)
NSDictionary *dict = array[indexPath. row ];
Student *s = [ Student new ];
[s setValuesForKeysWithDictionary :dict];
//cell 上显示数据
cell. textLabel . text = s. name ;
cell. detailTextLabel . text = s. phoneNumber ;
cell. imageView . image = [ UIImage imageNamed : @"mx.png" ];
return cell;
}
// 分区标题
-( NSString *)tableView:( UITableView *)tableView titleForHeaderInSection:( NSInteger )section{
return _grouparr [section];
}
// 索引
-( NSArray *)sectionIndexTitlesForTableView:( UITableView *)tableView{
return _grouparr ;
}
#pragma mark 页面跳转
-( void )tableView:( UITableView *)tableView didSelectRowAtIndexPath:( NSIndexPath *)indexPath{
DegaViewController *detaPage = [ DegaViewController new ];
// 取出分组对应的数组(找到对应分区)
NSArray *array = [ _dic objectForKey : _grouparr [indexPath. section ]];
// 取出具体的字典(找到对应的行)
NSDictionary *dict = array[indexPath. row ];
// 完成 model 赋值
Student *s = [ Student new ];
[s setValuesForKeysWithDictionary :dict];
// 传值
detaPage. stu = s;
// 跳转
[ self . navigationController pushViewController :detaPage animated : YES ];
}
#pragma mark tableView 移动
// 处于编辑状态(其他按钮的方法)
// 能否移动
-( BOOL )tableView:( UITableView *)tableView canMoveRowAtIndexPath:( NSIndexPath *)indexPath{
return YES ;
}
// 移动完成
-( void )tableView:( UITableView *)tableView moveRowAtIndexPath:( NSIndexPath *)sourceIndexPath toIndexPath:( NSIndexPath *)destinationIndexPath{
// 获取移动的数据
NSMutableArray *array = [ _dic objectForKey : _grouparr [sourceIndexPath. section ]];
NSDictionary *dict = [array objectAtIndex :sourceIndexPath. row ];
// 删除源数据
[array removeObjectAtIndex :sourceIndexPath. row ];
// 添加到要移动的目的地
[array insertObject :dict atIndex :destinationIndexPath. row ];
}
// 是否支持移动
-( NSIndexPath *)tableView:( UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:( NSIndexPath *)sourceIndexPath toProposedIndexPath:( NSIndexPath *)proposedDestinationIndexPath{
// 如果在一个分区,我们就可以让它留在这个分区
if (sourceIndexPath. section == proposedDestinationIndexPath. section ) {
return proposedDestinationIndexPath;
}
// 否则,哪来的回哪去
return sourceIndexPath;
}
DegaViewController.h :
//引入student的头文件
#import
"Student.h"
@interface DegaViewController : UIViewController
// 定义接受的 model 对象
@property ( nonatomic , retain ) Student *stu;
@interface DegaViewController : UIViewController
// 定义接受的 model 对象
@property ( nonatomic , retain ) Student *stu;
@end
DegaViewController.m :
- (
void
)viewDidLoad
{
[ super viewDidLoad ];
self . view . backgroundColor = [ UIColor cyanColor ];
// 姓名
{
[ super viewDidLoad ];
self . view . backgroundColor = [ UIColor cyanColor ];
// 姓名
UILabel *namelabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 200, 30)];
//赋值
namelabel.
text
=
_stu
.
name
;
[ self . view addSubview :namelabel];
// 性别
UILabel *genderlabel = [[ UILabel alloc ] initWithFrame : CGRectMake ( 100 , 150 , 200 , 30 )];
genderlabel. text = _stu . gender ;
[ self . view addSubview :genderlabel];
// 年龄
UILabel *agelabel = [[ UILabel alloc ] initWithFrame : CGRectMake ( 100 , 200 , 200 , 30 )];
agelabel. text = _stu . age ;
[ self . view addSubview :agelabel];
// 电话
UILabel *phoneNumberlabel = [[ UILabel alloc ] initWithFrame : CGRectMake ( 100 , 250 , 200 , 30 )];
phoneNumberlabel. text = _stu . phoneNumber ;
[ self . view addSubview :phoneNumberlabel];
// 爱好
UILabel *hobbylabel = [[ UILabel alloc ] initWithFrame : CGRectMake ( 100 , 300 , 200 , 30 )];
hobbylabel. text = _stu . hobby ;
[ self . view addSubview :hobbylabel];
[ self . view addSubview :namelabel];
// 性别
UILabel *genderlabel = [[ UILabel alloc ] initWithFrame : CGRectMake ( 100 , 150 , 200 , 30 )];
genderlabel. text = _stu . gender ;
[ self . view addSubview :genderlabel];
// 年龄
UILabel *agelabel = [[ UILabel alloc ] initWithFrame : CGRectMake ( 100 , 200 , 200 , 30 )];
agelabel. text = _stu . age ;
[ self . view addSubview :agelabel];
// 电话
UILabel *phoneNumberlabel = [[ UILabel alloc ] initWithFrame : CGRectMake ( 100 , 250 , 200 , 30 )];
phoneNumberlabel. text = _stu . phoneNumber ;
[ self . view addSubview :phoneNumberlabel];
// 爱好
UILabel *hobbylabel = [[ UILabel alloc ] initWithFrame : CGRectMake ( 100 , 300 , 200 , 30 )];
hobbylabel. text = _stu . hobby ;
[ self . view addSubview :hobbylabel];
}
Student.h中:
@interface
Student :
NSObject
@property ( nonatomic , retain ) NSString *name;
@property ( nonatomic , retain ) NSString *age;
@property ( nonatomic , retain ) NSString *gender;
@property ( nonatomic , retain ) NSString *phoneNumber;
@property ( nonatomic , retain ) NSString *hobby;
@property ( nonatomic , retain ) NSString *picture;
@property ( nonatomic , retain ) NSString *name;
@property ( nonatomic , retain ) NSString *age;
@property ( nonatomic , retain ) NSString *gender;
@property ( nonatomic , retain ) NSString *phoneNumber;
@property ( nonatomic , retain ) NSString *hobby;
@property ( nonatomic , retain ) NSString *picture;
@end