iOS_12_tableViewCell的删除更新_红楼梦

来源:互联网 发布:金山数据恢复大师vip 编辑:程序博客网 时间:2024/06/16 15:06

最终效果图:



Girl.h

////  Girl.h//  12_tableView的增删改////  Created by beyond on 14-7-27.//  Copyright (c) 2014年 com.beyond. All rights reserved.//#import <Foundation/Foundation.h>@interface Girl : NSObject// UI控件用weak,字符串用copy,其他对象用strong// 头像图片名@property(nonatomic,copy)NSString *headImgName;// 姓名@property(nonatomic,copy)NSString *name;// 判词@property(nonatomic,copy)NSString *verdict;// 提供一个类方法,即构造函数,返回封装好数据的对象(返回id亦可)+ (Girl *)girlNamed:(NSString *)name headImgName:(NSString*)headImgName verdict:(NSString *)verdict;// 类方法,字典 转 对象 类似javaBean一次性填充+ (Girl *)girlWithDict:(NSDictionary *)dict;// 对象方法,设置对象的属性后,返回对象- (Girl *)initWithDict:(NSDictionary *)dict;@end




Girl.m

////  Girl.m//  12_tableView的增删改////  Created by beyond on 14-7-27.//  Copyright (c) 2014年 com.beyond. All rights reserved.//#import "Girl.h"@implementation Girl// 提供一个类方法,即构造函数,返回封装好数据的对象(返回id亦可)+(Girl *)girlNamed:(NSString *)name headImgName:(NSString *)headImgName verdict:(NSString *)verdict{    Girl *girl = [[Girl alloc]init];    girl.name = name;    girl.headImgName = headImgName;    girl.verdict = verdict;    return girl;}// 类方法,字典 转 对象 类似javaBean一次性填充+ (Girl *)girlWithDict:(NSDictionary *)dict{    // 只是调用对象的initWithDict方法,之所以用self是为了对子类进行兼容    return [[self alloc]initWithDict:dict];}// 对象方法,设置对象的属性后,返回对象- (Girl *)initWithDict:(NSDictionary *)dict{    // 先调用父类NSObject的init方法    if (self = [super init]) {        // 设置对象自己的属性        self.name = dict[@"name"]   ;        self.headImgName = dict[@"headImg"] ;        self.verdict = dict[@"verdict"];    }    // 返回填充好的对象    return self;}@end




BeyondViewController.h

////  BeyondViewController.h//  12_tableView的增删改////  Created by beyond on 14-7-27.//  Copyright (c) 2014年 com.beyond. All rights reserved.//#import <UIKit/UIKit.h>@interface BeyondViewController : UIViewController// 标题@property (weak, nonatomic) IBOutlet UILabel *titleStatus;// tableView@property (weak, nonatomic) IBOutlet UITableView *tableView;// 清空按钮@property (weak, nonatomic) IBOutlet UIBarButtonItem *trashBtn;// 全选 反选按钮@property (weak, nonatomic) IBOutlet UIBarButtonItem *checkAllBtn;// 清空- (IBAction)trashBtnClick:(UIBarButtonItem *)sender;// 全选 or 反选- (IBAction)checkAll:(UIBarButtonItem *)sender;@end




BeyondViewController.m

////  BeyondViewController.m//  12_tableView的增删改////  Created by beyond on 14-7-27.//  Copyright (c) 2014年 com.beyond. All rights reserved.//#import "BeyondViewController.h"#import "Girl.h"@interface BeyondViewController ()<UITableViewDataSource,UITableViewDelegate>{    // 从plist文件中加载的所有girls,返回字典数组    NSArray *_arrayWithDict;    // 所有的对象数组    NSMutableArray *_girls;        // 被勾选的行的对应该的模型数组    // 不用数组也行,只要在模型中增加一个属性:记录是否被选中    NSMutableArray *_checkedGirls;}@end@implementation BeyondViewController- (void)viewDidLoad{    [super viewDidLoad];    // 所有的对象数组    _girls = [NSMutableArray array];    // 被勾选的行的数组    _checkedGirls = [NSMutableArray array];    // 调用自定义方法,加载plist文件    [self loadPlist];    }// 自定义方法,加载plist文件- (void)loadPlist{    // sg_bundle模板代码,1,获得.app主要的包;2,返回主要的包中某个文件的fullPath全路径    NSBundle *mainBundle = [NSBundle mainBundle];    NSString *fullPath = [mainBundle pathForResource:@"girls.plist" ofType:nil];        // 从plist文件中根据全路径,返回字典数组    _arrayWithDict = [NSArray arrayWithContentsOfFile:fullPath];        // 再调用自定义方法,将字典数组,转换成对象数组    [self dictArrayToModel];    }// 自定义方法,将字典数组,转换成对象数组- (void)dictArrayToModel{    // 字典数组 _arrayWithDict    // 方式1:for in,这种情况下,控制器知道的东西太多了,如果模型增加属性,还要改控制器中的代码    /*     for (NSDictionary *dict in _arrayWithDict) {          Girl *girl = [Girl girlNamed:dict[@"name"] headImgName:dict[@"headImg"] verdict:dict[@"verdict"]];     [_girls addObject:girl];     }     */            // 方式2:类方法返回对象,参数只要一个字典数组即可    for (NSDictionary *dict in _arrayWithDict) {        // 参数只要字典,这样一来,控制器就不用知道太多东西了        // Girl *girl = [[Girl alloc]initWithDict:dict];        Girl *girl = [Girl girlWithDict:dict];                [_girls addObject:girl];    }}// 数据源方法,默认是单组,共有多少行 (每次刷新数据都会调用此行)- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{                // 返回数组中对应的字典的长度    return _girls.count;}// 数据源方法,每一组的每一行应该显示怎么的界面(含封装的数据),重点!!!必须实现否则,Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{                    static NSString *cellID = @"Beyond";    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];    if (cell == nil) {        // 如果池中没取到,则重新生成一个cell        /*         cell的4种样式:         1,default   左图右文字         2,subtitle  左图  上文字大    下文字小         3,value 1   左图  左文字大    右文字小         3,value 2   恶心  左文字小    右文字大         */        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];    }    // 设置cell中独一无二的内容    Girl *girl = _girls[indexPath.row];    cell.textLabel.text = girl.name;    cell.imageView.image = [UIImage imageNamed:girl.headImgName];    cell.detailTextLabel.text = girl.verdict;    // 判断,如果模型存在于checkedArray中,则标记为checked    if ([_checkedGirls containsObject:girl]) {        cell.accessoryType = UITableViewCellAccessoryCheckmark;    } else {        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;    }    // 返回cell    return cell;}// 代理方法,每一行的高度- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{    return 83;}// 代理方法,点击行,新版本 MVC- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{    // 取消tableView点击后背景高亮的蓝色    [tableView deselectRowAtIndexPath:indexPath animated:YES];        // 获得被点击的行的对应的数据模型    Girl *girl = [_girls objectAtIndex:indexPath.row];        // 判断,若没被勾选过,则勾选,否则取消勾选    // 方式2:只修改模型,不动cell,让tableView reload数据即可,符合MVC~    if ([_checkedGirls containsObject:girl]) {        // 取消勾选,从勾选数组中移除,然后再次reloadData        [_checkedGirls removeObject:girl];    } else {        // 加入到选中数组中,然后再次reloadData!        [_checkedGirls addObject:girl];    }        // 再次reloadData    [_tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];            // 最后调用自定义方法,检查trash按钮的可用性,以及标题的变化    [self statusCheck];        }// 代理方法,点击行----旧版本- (void)oldVersionTableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{    // 取消tableView点击后背景高亮的蓝色    [tableView deselectRowAtIndexPath:indexPath animated:YES];        // 获得被点击的行    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];    // 获得被点击的行的对应的数据模型    Girl *girl = [_girls objectAtIndex:indexPath.row];            // 判断,若没被勾选过,则勾选,否则取消勾选    // 方式1:手动设置cell的样式,但是,这不符合MVC思想~    /*     if (cell.accessoryType != UITableViewCellAccessoryCheckmark) {     // 勾选上,同时要加入到数组中,记住!     cell.accessoryType = UITableViewCellAccessoryCheckmark;          [_checkedGirls addObject:girl];          } else {     // 取消勾选,同时要移除     cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;     [_checkedGirls removeObject:girl];     }     */        // 方式2:只修改模型,不动cell,让tableView reload数据即可,符合MVC~    if (cell.accessoryType != UITableViewCellAccessoryCheckmark) {        // 加入到选中数组中,然后再次reloadData!        [_checkedGirls addObject:girl];        [_tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];    } else {        // 取消勾选,从勾选数组中移除,然后再次reloadData        [_checkedGirls removeObject:girl];        [_tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];    }                // 最后调用自定义方法,检查trash按钮的可用性,以及标题的变化    [self statusCheck];}// 当点击了toolBar中的trash 按钮时调用- (IBAction)trashBtnClick:(UIBarButtonItem *)sender {                       // 可变数组,成员是所有的勾选的行组成的indexPath    NSMutableArray *indexPaths = [NSMutableArray array];    // 遍历checkedGirls,得到勾选的行号们,并封装成一个个indexPath,然后添加到indexPaths数组,目的是后面tableView删除行方法中用到    for (Girl *girl in _checkedGirls) {        // 勾选的行的行号        int row = [_girls indexOfObject:girl];        // 封装成IndexPath        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:0];        // 添加到IndexPaths数组        [indexPaths addObject:indexPath];    }                // 先修改模型(从所有的对象数组中删除 勾选的对象们,并且清空勾选的对象数组),最后再deleteRowsAtIndexPaths(注意reload前提是数据源个数不能增加或减少)    [_girls removeObjectsInArray:_checkedGirls];    [_checkedGirls removeAllObjects];    // deleteRows删除行之后,剩余的行数,必须与数据源的行数相等,意思就是:数据源中也要删除同样多的行的数据,才可以调用deleteRows方法    [_tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];        // 最后调用自定义方法,检查trash按钮的可用性,以及标题的变化    [self statusCheck];}// 最后调用自定义方法,检查trash按钮的可用性,以及标题的变化- (void)statusCheck{        // 如果表格没有数据了,则直接禁用掉全选按钮    if (_girls.count == 0) {        _checkAllBtn.enabled = NO;    }                    // 设置显示checked的行数    if (_checkedGirls.count != 0) {        // 如果没有被选中的行,则禁用 删除按钮        _trashBtn.enabled = YES;        // 显示数字(默认bar button item中的文本是不可更改的,所以改成label标签)        NSString *titleStatus = [NSString stringWithFormat:@"红楼梦(%d)",_checkedGirls.count];        _titleStatus.text = titleStatus;    } else {        _trashBtn.enabled = NO;        _titleStatus.text = @"红楼梦";    }}// toolBar最右边的 全选 or 反选按钮- (IBAction)checkAll:(UIBarButtonItem *)sender {            if (_girls.count == _checkedGirls.count) {        // 取消全选   先修改模型,再reload        [_checkedGirls removeAllObjects];        [_tableView reloadData];    } else {        // 全选   先修改模型,再reload        // 必须先清空checked数组,再全部添加        [_checkedGirls removeAllObjects];        [_checkedGirls addObjectsFromArray:_girls];        [_tableView reloadData];    }        // 调用自定义方法 修改检测状态    [self statusCheck];            }@end





属性列表文件girls.plist





main.storyboard 

因为bar button item的文字不可更改, 遂换成label,

label不接收点击事件,所以可以向后传递给button处理点击事件






1 0