1.在一个表格中可以对行元素进行删除,插入,和移动操作,
2.点击一个行元素,可以进入第二页面对内容进行修改。
效果展示:
实现步骤:
1.新建一个Movie类,这个类相当于MVC中的M,里面是视图中要用到的成员变量:
其中头文件定义如下,然后NSCopying,NSCoding等协议的实现,这里不做介绍
代码如下:
#import <Foundation/Foundation.h>
@interface Moves : UIViewController<NSCopying,NSCoding>{
NSString* title;//电影标题
NSNumber* boxOfficeGross;//票房
NSString* summary;//简介
}
@property (nonatomic,copy)NSString * title;
@property(nonatomic,copy)NSNumber *boxOfficeGross;
@property (nonatomic,copy)NSString *summary;
-(id)initWithTitile:(NSString*)NewTitle andBoxoffice:(NSInteger)NewBox andSummary:(NSString*)NewSummary;
-(NSString *)description;
@end
2.新建一个MainTableViewController类,然后将它加入到根视图中:具体代码如下:
MainTableViewController *myView = [[MainTableViewController alloc]init];
UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:myView];
self.window.rootViewController = navi;
3.由于我的数据都是在Plist文件中存放,所以我建立了一个plist文件,具体信息如下:
4.首先我先在头文件中定义一个可变数组,和一个Movie对象作为成员参数:
@interface MainTableViewController : UITableViewController
{
NSMutableArray *array;
Moves *reloadMovie;
}
然后我们把plist中的信息引入到我们的类中,然后进行显示到视图上面:
(1):初始化函数,在viewDidLoad中调用即可:代码如下:
-(void)initData{
array = [[NSMutableArray alloc]initWithCapacity:5];
NSString *path = [[NSBundle mainBundle ]pathForResource:@"MovieData" ofType:@"plist"];
NSArray *arr = [NSArray arrayWithContentsOfFile:path];
for (int i= 0; i<arr.count; i++) {
NSDictionary *dic = [arr objectAtIndex:i];
Moves *mm = [[Moves alloc]initWithTitile:[dic objectForKey:@"title"] andBoxoffice:[[dic objectForKey:@"boxOfficeGross"]integerValue] andSummary:[dic objectForKey:@"summary"]];
[array addObject:mm];
}
}
(2)把plist里面的数据,都放入到表格中:然后写编辑器给我提供的方法(被注释掉的,取消掉即可)
#pragma mark -UITableViewCell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{ //CellIdentifier只是一个标识符,当重用的时候,可以让已经消失的表格行加以复用;
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {//单元格的重用,只显示一个屏幕的CELL,多余的进行和消失的进行内容和位置的替换。
cell = [[UITableViewCell alloc]initWithStyle:1 reuseIdentifier:CellIdentifier];
//辅助单元格的样式
cell.accessoryType = 1;
}
Moves *mm = [array objectAtIndex:indexPath.row];
cell.textLabel.text = mm.title;
cell.detailTextLabel.text = [NSString stringWithFormat:@"%@",mm.boxOfficeGross];
//NSLog(@"%@",[array objectAtIndex:indexPath.row]);
return cell;
}
(3):这时候一定要设置表格要显示的行数和区域,不然整个表格仍然为空:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return array.count;
}
5.一个简单的表格已经初始化完毕,这时候我们发现我们的表格虽然有编辑选项,但是不能真正的实现,
下面我们就开始实现对表格的插入,删除操作。
(1)设置单元格的编辑样式,默认为delete:
实现效果:一行选项为删除,一行选项为插入:
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row % 2) {
return UITableViewCellEditingStyleInsert;
}else{
return UITableViewCellEditingStyleDelete;
}
}
(2)表格的删除和插入:
#pragma mark 编辑模式的删除与插入
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
//删除数组中的选定元素:
[array removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
//创建一个新的类的实例,插入到数组中,并且添加一个新的行到这个表格视图中去
static int i= 0;
NSString *str = [NSString stringWithFormat:@"捉妖记%d",++i];
Moves *mm = [[Moves alloc]initWithTitile:str andBoxoffice:12343 andSummary:@"a good movie"];
[array addObject:mm];
//确定插入行的位置
NSIndexPath *insertIndex = [NSIndexPath indexPathForRow:array.count - 1 inSection:indexPath.section];
//把新建的行的数据进行插入到表格中:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:insertIndex,nil] withRowAnimation:UITableViewRowAnimationFade];
}
}
(3):表格行元素的移动:
注意:这里一定要先删除在插入,因为如果你先插入的时候,行数就会增加一行,时候,在下移的时候,就会出错。
#pragma mark 移动行的位置,
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
//原理:先进行copy一份,然后把复制的插入要移动到的位置,然后把原来的进行删除操作。
//1.获取到需要系统的位置,
Moves *fromObject = [array objectAtIndex:fromIndexPath.row];
//2.把获取到的数据进行copy给一个新的实例变量
Moves *toObject = [fromObject copy];
//3.然后删除原来的创建的实例变量。
[array removeObject:fromObject];
//4.把copy到的对象进行插入操作
[array insertObject:toObject atIndex:toIndexPath.row];
[tableView reloadData];
}
通过以上的操作,我们就可以就表格进行简单的删除,插入,和移动操作了。接下来我们就要进行内容的修改操作了。
分析:我们应该新建一个viewcontroller的视图,然后里面存放我们Movie里面的数据,当我们进行修改数据的时候,
直接在返回的返回到主页面的时候,刷新数据就行了
6.新建一个DetailViewController类,同样的我们引入Movie的对象作为成员变量,然后用xib进行简单的页面布局,并初始化
初始值为Movie里面的数据:
(1):头文件代码如下:
#import <UIKit/UIKit.h>
#import "Moves.h"
@interface MovieEditViewController : UIViewController<UITextFieldDelegate>
// 以下三个用来存放电影的三个数据
@property (strong, nonatomic) IBOutlet UITextField *MovieName;
@property (strong, nonatomic) IBOutlet UITextField *MovieCount;
@property (strong, nonatomic) IBOutlet UITextField *MovieMes;
@property (nonatomic,strong)Moves *EditMovie;
//用来返回页面:
-(void)Return;
@end
(2):成员变量的初始化函数,独立的,需要在viewDidLoad中调用:
-(void)initData{
self.MovieName.text = _EditMovie.title;
self.MovieCount.text = [NSString stringWithFormat:@"%@",_EditMovie.boxOfficeGross];
self.MovieMes.text = _EditMovie.summary;
}
(3):在页面要跳转的时候。我们要对Movie中的数据进行重新复制:重写viewWillDisappear方法:
-(void)viewWillDisappear:(BOOL)animated{
_EditMovie.title = self.MovieName.text;
_EditMovie.boxOfficeGross = (NSNumber*)self.MovieCount.text;
_EditMovie.summary = self.MovieMes.text;
}
做到这一步。我们的大概模型已经做好了,剩下的就是一些小细节,例如:
1.在编辑的时候,点击textFile,虚拟键盘出现,但不会自动的隐藏:
解决办法:重写系统提供的方法:
前提:遵守UITextFieldDelegate协议,然后,在viewDidLoad中,设置当前的控件为第一响应者:例如:
self.MovieMes.delegate =self;
self.MovieName.delegate =self;
self.MovieCount.delegate =self;
然后在我们触摸空白处的时候。还有就是点击了键盘的return的时候我们让虚拟键盘自动隐藏:
原理:都是让文本框结束第一响应者,也就是文本框的优先级降低,让虚拟键盘消失
三个方法如下:
(1):
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.MovieCount resignFirstResponder];
[self.MovieMes resignFirstResponder];
[self.MovieName resignFirstResponder];
}
(2)
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[self.MovieCount resignFirstResponder];
[self.MovieMes resignFirstResponder];
[self.MovieName resignFirstResponder];
return YES;
}
解决办法:重写系统提供的方法:当我们开始编辑的时候,让真个view的坐标向上移动,然后结束编辑的时候,再
变为原来的坐标:
代码如下:
(1):
//开始编辑的时候
- (void)textFieldDidBeginEditing:(UITextField *)textField{
if (textField == self.MovieMes) {
//给向上移动一个动画的效果
[UIView animateWithDuration:0.6 animations:^{
self.view.frame = CGRectMake(0, -110, self.view.frame.size.width, self.view.frame.size.height);
}];
}
}
//结束编辑的时候
- (void)textFieldDidEndEditing:(UITextField *)textField{
if (textField == self.MovieMes) {
[UIView animateWithDuration:0.6 animations:^{
self.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}];
}
}
注意:我们对表格中数据的更新一般用reloadData方法。但是。如果我们的plist里面的数据很多的时候,我们仍然用这种方法
效率是很低很低的,这时候我们就应该想着局部更新,以提高效率,所以,我用了以下方法:
#pragma mark -刷新
-(void)viewWillAppear:(BOOL)animated{
//[self.tableView reloadData];该方法书写简单,但是效率低下
if (reloadMovie) {
//获取到修改的元素的行号
NSUInteger row = [array indexOfObject:reloadMovie];
NSIndexPath *indexpath = [NSIndexPath indexPathForRow:row inSection:0];
//对获取到的行的数据进行跟新
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexpath] withRowAnimation:NO];
}
}
讲解完毕:可能有些地方说的不是太清楚,感兴趣的朋友可以留下邮箱。我会给你我的源代码进行参考。