UITableView
创建UITableView
-
代码
-
使用Masonry布局
-
storyboard
- 动态单元格记得使用唯一标识符a
- xib和storyboard差不多
注意点:循环利用 有if就有else
刷新数据
- 全局刷新
[self.table reloadData];
- 局部刷新
- 添加(带动画)
[self.wineArr insertObject:wine atIndex:0];
NSArray *indepath = @[[NSIndexPath indexPathForRow:0 inSection:0]];
[self.table insertRowsAtIndexPaths:indepath withRowAnimation:UITableViewRowAnimationRight];
- 删除(带动画)
NSArray *delate =@[[NSIndexPath indexPathForRow:0 inSection:0]];
[self.table deleteRowsAtIndexPaths:delate withRowAnimation:UITableViewRowAnimationMiddle];
- 刷新(带动画)
NSArray *update =@[[NSIndexPath indexPathForRow:0 inSection:0]];
[self.table reloadRowsAtIndexPaths:update withRowAnimation:UITableViewRowAnimationMiddle];
左划删除
#pragma make - UITbaleViewDalegate
/** 只要有这个方法就会出现向左划就会出现删除按钮,点击按钮会调用这个方法(iOS9以前一定要调用这个方法才会出现,但是在iOS9后只要调用下面的方法一样可以出现按钮)*/
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.wineArr removeObjectAtIndex:indexPath.row];
NSArray *delate =@[
[NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section]
];
[self.table deleteRowsAtIndexPaths:delate withRowAnimation:UITableViewRowAnimationMiddle];
}
/** 这个方法返回的字符串是你要现实在左划按钮上面显示的字,如何和下面方法同时存在下面方法优先级更高*/
-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return @"删除";
}
//自定义左划的按钮
-(NSArray<UITableViewRowAction *>*)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
//这是代表一个按钮 block里面的代码是点击这个按钮之后会执行的操作
UITableViewRowAction *action1 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除a" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
//和上面删除的方法相同代码
[self.wineArr removeObjectAtIndex:indexPath.row];
NSArray *delate =@[
[NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section]
];
[self.table deleteRowsAtIndexPaths:delate withRowAnimation:UITableViewRowAnimationMiddle];
}];
UITableViewRowAction * action2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"关注" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
//这个方法只是展示用,现在不推荐使用
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"谢谢关注" message:@"😘" delegate:nil cancelButtonTitle:@"关闭" otherButtonTitles:nil, nil];
alert.show;
//推出编辑模式
self.table.editing = NO;
}];
//先加的按钮在右边
return @[action1,action2];
}
编辑模式
//让tabel进入编辑模式
//取反 是编辑模式久让它变成不是 否则相反
self.table.editing = !self.table.editing;
//带动画的方法
[self.table setEditing:!self.table.isEditing animated:YES];
多行编辑模式下的删除
- (void)viewDidLoad {
[super viewDidLoad];
//让批量删除可以多选,默认有一个样式
self.table.allowsMultipleSelectionDuringEditing = YES;
//删除按钮状态
self.ddd.enabled = NO;
}
//批量删除按钮
- (IBAction)remove {
//让tabel进入编辑模式
//取反 是编辑模式久让它变成不是 否则相反
//self.table.editing = !self.table.editing;
//带动画的方法
[self.table setEditing:!self.table.isEditing animated:YES];
self.ddd.enabled = !self.ddd.enabled;
}
//删除按钮
- (IBAction)deleate {
//零时数组保存数据
NSMutableArray *tempArr = [NSMutableArray array];
//注意:千万不要一边遍历数组,一边操作这个数组,因为数组中的索引会一直发生变化
for (NSIndexPath *indexpath in self.table.indexPathsForVisibleRows) {
[tempArr addObject:self.wineArr[indexpath.row]];
}
//在数据源中把用户选择的数据删除
[self.wineArr removeObjectsInArray:tempArr];
//tableVieW删除这些列表
[self.table deleteRowsAtIndexPaths:self.table.indexPathsForVisibleRows withRowAnimation:UITableViewRowAnimationAutomatic];
}
1.png
自定义编辑模式多选的按钮
首先模型中增加一个属性
@property(assign,nonatomic,getter=ischeck)BOOL check;
让后自定义cell中重写方法
//重写initWithStyle方法
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
UIImageView *checkImage = [[UIImageView alloc]init];
checkImage.image = [UIImage imageNamed:@"check"];
checkImage.hidden = YES;
[self.contentView addSubview:checkImage];
self.check = checkImage;
}
return self;
}
//布局子控件
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat WH = 24;
CGFloat X = self.contentView.frame.size.width - WH- 10;
CGFloat Y = (self.contentView.frame.size.height - WH)*0.5;
self.check.frame = CGRectMake(X, Y, WH, WH);
}
//设置数据
- (void)setWine:(Wine *)wine
{
_wine = wine;
self.imageView.image = [UIImage imageNamed:wine.image];
self.textLabel.text = wine.name;
self.detailTextLabel.text = wine.money;
//根据传进来的模型判断是否显示打勾的图片
if (wine.ischeck) {
self.check.hidden = NO;
}else
{
self.check.hidden = YES;
}
}
重点就是声明一个数组,用来保存用户选取的哪个
/** 用户选取要删除的数组*/
@property(strong,nonatomic)NSMutableArray *SelectArr;
//懒加载
- (NSMutableArray *)SelectArr
{
if (!_SelectArr) {
_SelectArr = [NSMutableArray array];
}
return _SelectArr;
}
#pragma mark - UITableViewDalegate
//监听用户选点击了哪一行
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Wine *wine = self.WineArr[indexPath.row];
if (wine.ischeck) {
wine.check = NO;
[self.SelectArr removeObject:indexPath];
}else{
wine.check = YES;
[self.SelectArr addObject:indexPath];
}
NSLog(@"%@",indexPath);
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
//删除方法
- (IBAction)deleate {
NSMutableArray *tempArr = [NSMutableArray array];
for (NSIndexPath *indexpatha in self.SelectArr) {
[tempArr addObject:self.WineArr[indexpatha.row]];
}
//删除数据源中的数据
[self.WineArr removeObjectsInArray:tempArr];
[self.Tabel deleteRowsAtIndexPaths:self.SelectArr withRowAnimation:UITableViewRowAnimationAutomatic];
//重置数组为
[self.SelectArr removeAllObjects];
}
通知
- (void)viewDidLoad {
[super viewDidLoad];
//监听通知
NSNotificationCenter *Notice = [NSNotificationCenter defaultCenter];
[Notice addObserver:self selector:@selector(countAdd:) name:@"AddCount" object:nil];
[Notice addObserver:self selector:@selector(countRemove:) name:@"RemoveCount" object:nil];
}
//在销毁前移除通知
- (void)dealloc
{
[[NSNotificationCenter defaultCenter]removeObserver:self];
}
-(void)countAdd:(NSNotification *)note
{ //发布者
WineTableViewCell *cell = note.object;
int price = self.Price.text.intValue + cell.wine.money.intValue;
self.Price.text = [NSString stringWithFormat:@"%d",price];
}
-(void)countRemove:(NSNotification *)note
{
//发布者
WineTableViewCell *cell = note.object;
int price = self.Price.text.intValue - cell.wine.money.intValue;
self.Price.text = [NSString stringWithFormat:@"%d",price];
}
- (IBAction)add {
self.wine.count ++;
self.count.text = [NSString stringWithFormat:@"%ld",(long)self.wine.count];
self.remove.enabled = YES;
//发布通知
[[NSNotificationCenter defaultCenter]postNotificationName:@"AddCount" object:self];
}
- (IBAction)deleate {
self.wine.count --;
self.count.text = [NSString stringWithFormat:@"%ld",(long)self.wine.count];
if (self.wine.count==0) {
self.remove.enabled = NO;
}
//发布通知
[[NSNotificationCenter defaultCenter]postNotificationName:@"RemoveCount" object:self];
}
block写法不要移除 执行block中的代码块
// 监听通知
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserverForName:@"plusClickNotification" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
// 发布者
XMGWineCell *cell = note.object;
// 计算总价
int totalPrice = self.totalPriceLabel.text.intValue + cell.wine.money.intValue;
// 设置总价
self.totalPriceLabel.text = [NSString stringWithFormat:@"%d",totalPrice];
}];
kvo
@implementation ViewController
- (NSMutableArray *)WineData
{
if (!_WineData) {
_WineData = [Wine mj_objectArrayWithFilename:@"wine.plist"];
//监听属性变化
for (Wine *wine in _WineData) {
[wine addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
}
}
return _WineData;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
//移除KVO
- (void)dealloc
{
for (Wine *wine in _WineData) {
[wine removeObserver:self forKeyPath:@"count"];
}
}
#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(Wine*)wine change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
int new = [change[NSKeyValueChangeNewKey] intValue];
int old = [change[NSKeyValueChangeOldKey]intValue];
if (new>old) {
int price = self.Price.text.intValue + wine.money.intValue;
self.Price.text = [NSString stringWithFormat:@"%d",price];
self.buyBtn.enabled = YES;
}else
{
int price = self.Price.text.intValue - wine.money.intValue;
self.Price.text = [NSString stringWithFormat:@"%d",price];
self.buyBtn.enabled = (price>0);
}
}
block写法
- 缺点:在类中一使用到就会调用了
- 如果一个类使用来kvo监听,苹果木默认会给这个类生成一个子类,在子类中监听这些事情
代理
#import <UIKit/UIKit.h>
@class Wine,WineTableViewCell;
/** 代理*/
@protocol WineTableViewCellDalegate <NSObject>
@optional
-(void)wineCellClickAddBtn:(WineTableViewCell *)wine;
-(void)wineCellClickDeleateBtn:(WineTableViewCell *)wine;
@end
@interface WineTableViewCell : UITableViewCell
/** 模型*/
@property(strong,nonatomic)Wine *wine;
/** 代理属性*/
@property(weak,nonatomic)id <WineTableViewCellDalegate> delegate;
@end
@implementation WineTableViewCell
/** 代理*/
if ([self.delegate respondsToSelector:@selector(wineCellClickAddBtn:)]) {
[self.delegate wineCellClickAddBtn:self];
}
/** 代理*/
if ([self.delegate respondsToSelector:@selector(wineCellClickDeleateBtn:)]) {
[self.delegate wineCellClickDeleateBtn:self];
}
//设置代理
cell.delegate = self;
//遵守协议
@interface ViewController ()<UITableViewDataSource,UITableViewDelegate,WineTableViewCellDalegate>
//实现方法
#pragma mark - WineTableViewCellDalegate
-(void)wineCellClickAddBtn:(WineTableViewCell *)wine
{
int price = self.Price.text.intValue + wine.wine.money.intValue;
self.Price.text = [NSString stringWithFormat:@"%d",price];
self.buyBtn.enabled = YES;
//添加到购物车
if (![self.shopping containsObject:wine.wine])
{
[self.shopping addObject:wine.wine];
}
}
-(void)wineCellClickDeleateBtn:(WineTableViewCell *)wine
{
int price = self.Price.text.intValue - wine.wine.money.intValue;
self.Price.text = [NSString stringWithFormat:@"%d",price];
self.buyBtn.enabled = (price>0);
//移除购物车
if (wine.wine.count==0) {
[self.shopping removeObject:wine.wine];
}
}
网友评论