终于效果图:

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;
// 清空button
@property (weak, nonatomic) IBOutlet UIBarButtonItem *trashBtn;
// 全选 反选button
@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]; // 最后调用自己定义方法,检查trashbutton的可用性,以及标题的变化
[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];
} // 最后调用自己定义方法,检查trashbutton的可用性,以及标题的变化
[self statusCheck];
} // 当点击了toolBar中的trash button时调用
- (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]; // 最后调用自己定义方法,检查trashbutton的可用性,以及标题的变化
[self statusCheck];
} // 最后调用自己定义方法,检查trashbutton的可用性,以及标题的变化
- (void)statusCheck
{ // 假设表格没有数据了,则直接禁用掉全选button
if (_girls.count == 0) {
_checkAllBtn.enabled = NO;
} // 设置显示checked的行数
if (_checkedGirls.count != 0) {
// 假设没有被选中的行,则禁用 删除button
_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 反选button
- (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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcHJlX2VtaW5lbnQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

main.storyboard

由于bar button item的文字不可更改, 遂换成label,

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

iOS_12_tableViewCell的删除更新_红楼梦的更多相关文章

  1. GridView总结二:GridView自带编辑删除更新

    GridView自带编辑删除更新逻辑很简单:操作完,重新绑定.总结总结,防止忘记... 效果图: 前台代码: <%@ Page Language="C#" AutoEvent ...

  2. 简单的php Mysql类(查询 删除 更新)

    php Mysql类一般都包括了几乎我们常用的数据库操作方法,这里只提供了查询 删除 更新三种操作,算不是很全只是一个简单的数据库查询类了.      代码如下 复制代码 class mysql { ...

  3. iOS_10_tableView的简单使用_红楼十二钗

    终于效果图: 方式1,用字典数组 BeyondViewController.h // // BeyondViewController.h // 10_tableView // // Created b ...

  4. 用R进行文本分析初探——以《红楼梦》为例

    一.写在前面的话~ 刚吃饭的时候同学问我,你为什么要用R做文本分析,你不是应该用R建模么,在我和她解释了一会儿后,她嘱咐我好好写这篇博文,嗯为了娟儿同学,细细说一会儿文本分析. 文本数据挖掘(Text ...

  5. Python3红楼梦人名出现次数统计分析

    一.程序说明 本程序流程是读取红楼梦txt文件----使用jieba进行分词----借助Counter读取各人名出现次数并排序----使用matplotlib将结果可视化 这里的统计除了将“熙凤”出现 ...

  6. 红楼梦人物关系图,一代大师成绝响,下回分解待何人,kindle读书摘要

      人物关系图: https://www.cnblogs.com/images/cnblogs_com/elesos/1120632/o_2033091006.jpg 红楼梦 (古典名著普及文库) ( ...

  7. 红楼梦3d游戏

    1. 红楼梦大观园2d图 2. 红楼梦3d图 潇湘馆 注册机:根据电脑名和时间生成一个id,然后根据注册机生成注册码.

  8. Google BERT应用之《红楼梦》对话人物提取

    Google BERT应用之<红楼梦>对话人物提取 https://www.jiqizhixin.com/articles/2019-01-24-19

  9. 朴素贝叶斯文本分类-在《红楼梦》作者鉴别的应用上(python实现)

    朴素贝叶斯算法简单.高效.接下来我们来介绍其如何应用在<红楼梦>作者的鉴别上. 第一步,当然是先得有文本数据,我在网上随便下载了一个txt(当时急着交初稿...).分类肯定是要一个回合一个 ...

随机推荐

  1. PHP杂技(一)

    逻辑运算符 &&和& ||和|的部分区别 返回结果类型不同, A||B 如果A为真那么B不会做判断,而A|B前后都做判断 switch判断中并不是===,更像是==,例如(1) ...

  2. 异常详细信息: System.Data.SqlClient.SqlException: 用户 'NT AUTHORITY\IUSR' 登录失败解决办法

    最近在做.net项目,因为本人以前做java较多,所以对.net不熟悉,在项目完成后部署到IIS服务器上出现诸多问题,以上其中之一,若有时间,在更新其他问题的解决办法! 异常详细信息: System. ...

  3. 解决v-for产生的警告的办法

    当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略.如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且 ...

  4. python 修饰器 最好的讲解

    Python的修饰器的英文名叫Decorator,修饰器就是对一个已有的模块做一些“修饰工作”,比如在现有的模块加上一些小装饰(一些小功能,这些小功能可能好多模块都会用到),但又不让这个小装饰(小功能 ...

  5. LeetCode OJ--Binary Tree Level Order Traversal II

    http://oj.leetcode.com/problems/binary-tree-level-order-traversal-ii/ 树的层序遍历,和上一道题相比,对结果做一个顺序调整 reve ...

  6. vSphere Client 更改 ESX/ESXi 主机的端口

    https://blog.csdn.net/hanzheng260561728/article/details/51283808?locationNum=8&fps=1

  7. Codeforces Gym101502 K.Malek and Summer Semester

    K. Malek and Summer Semester   time limit per test 1.0 s memory limit per test 256 MB input standard ...

  8. Socks5代理Socks5 Proxy

    Socks5代理Socks5 Proxy   Socks5代理是基于Socks协议的一种代理模式.其中,5表示该协议的版本号.它可以让局域网的计算机通过socks5代理服务器,访问外网的内容.由于它工 ...

  9. HDU 3534 Tree (经典树形dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3534 题意: 给你一棵树,问你有多少对点的距离等于树的直径. 思路: dp[i][0]表示在i的子树中 ...

  10. android学习资源

    https://codelabs.developers.google.com/ https://developer.android.com/ http://v.youku.com/v_show/id_ ...