UITableView
創(chuàng)建UITableView
代碼
使用Masonry布局
-
storyboard
- 動態(tài)單元格記得使用唯一標識符a
- xib和storyboard差不多
注意點:循環(huán)利用 有if就有else
刷新數(shù)據(jù)
- 全局刷新
[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
/** 只要有這個方法就會出現(xiàn)向左劃就會出現(xiàn)刪除按鈕,點擊按鈕會調(diào)用這個方法(iOS9以前一定要調(diào)用這個方法才會出現(xiàn),但是在iOS9后只要調(diào)用下面的方法一樣可以出現(xiàn)按鈕)*/
-(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];
}
/** 這個方法返回的字符串是你要現(xiàn)實在左劃按鈕上面顯示的字,如何和下面方法同時存在下面方法優(yōu)先級更高*/
-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return @"刪除";
}
//自定義左劃的按鈕
-(NSArray<UITableViewRowAction *>*)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
//這是代表一個按鈕 block里面的代碼是點擊這個按鈕之后會執(zhí)行的操作
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:@"關(guān)注" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
//這個方法只是展示用,現(xiàn)在不推薦使用
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"謝謝關(guān)注" message:@"??" delegate:nil cancelButtonTitle:@"關(guān)閉" 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;
//刪除按鈕狀態(tài)
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 {
//零時數(shù)組保存數(shù)據(jù)
NSMutableArray *tempArr = [NSMutableArray array];
//注意:千萬不要一邊遍歷數(shù)組,一邊操作這個數(shù)組,因為數(shù)組中的索引會一直發(fā)生變化
for (NSIndexPath *indexpath in self.table.indexPathsForVisibleRows) {
[tempArr addObject:self.wineArr[indexpath.row]];
}
//在數(shù)據(jù)源中把用戶選擇的數(shù)據(jù)刪除
[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);
}
//設(shè)置數(shù)據(jù)
- (void)setWine:(Wine *)wine
{
_wine = wine;
self.imageView.image = [UIImage imageNamed:wine.image];
self.textLabel.text = wine.name;
self.detailTextLabel.text = wine.money;
//根據(jù)傳進來的模型判斷是否顯示打勾的圖片
if (wine.ischeck) {
self.check.hidden = NO;
}else
{
self.check.hidden = YES;
}
}
重點就是聲明一個數(shù)組,用來保存用戶選取的哪個
/** 用戶選取要刪除的數(shù)組*/
@property(strong,nonatomic)NSMutableArray *SelectArr;
//懶加載
- (NSMutableArray *)SelectArr
{
if (!_SelectArr) {
_SelectArr = [NSMutableArray array];
}
return _SelectArr;
}
#pragma mark - UITableViewDalegate
//監(jiān)聽用戶選點擊了哪一行
- (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]];
}
//刪除數(shù)據(jù)源中的數(shù)據(jù)
[self.WineArr removeObjectsInArray:tempArr];
[self.Tabel deleteRowsAtIndexPaths:self.SelectArr withRowAnimation:UITableViewRowAnimationAutomatic];
//重置數(shù)組為
[self.SelectArr removeAllObjects];
}
通知
- (void)viewDidLoad {
[super viewDidLoad];
//監(jiān)聽通知
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
{ //發(fā)布者
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
{
//發(fā)布者
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;
//發(fā)布通知
[[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;
}
//發(fā)布通知
[[NSNotificationCenter defaultCenter]postNotificationName:@"RemoveCount" object:self];
}
block寫法不要移除 執(zhí)行block中的代碼塊
// 監(jiān)聽通知
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserverForName:@"plusClickNotification" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
// 發(fā)布者
XMGWineCell *cell = note.object;
// 計算總價
int totalPrice = self.totalPriceLabel.text.intValue + cell.wine.money.intValue;
// 設(shè)置總價
self.totalPriceLabel.text = [NSString stringWithFormat:@"%d",totalPrice];
}];
kvo
@implementation ViewController
- (NSMutableArray *)WineData
{
if (!_WineData) {
_WineData = [Wine mj_objectArrayWithFilename:@"wine.plist"];
//監(jiān)聽屬性變化
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寫法
- 缺點:在類中一使用到就會調(diào)用了
- 如果一個類使用來kvo監(jiān)聽,蘋果木默認會給這個類生成一個子類,在子類中監(jiān)聽這些事情
代理
#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];
}
//設(shè)置代理
cell.delegate = self;
//遵守協(xié)議
@interface ViewController ()<UITableViewDataSource,UITableViewDelegate,WineTableViewCellDalegate>
//實現(xiàn)方法
#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];
}
}