IOSday09代理.KVO. 通知.tableView的编辑模式
代理的使用步骤
- 定义一份代理协议
- 协议名字的格式一般是:类名 + Delegate
- 比如UITableViewDelegate
- 代理方法细节
- 一般都是@optional
- 方法名一般都以类名开头
- 比如
- (void)scrollViewDidScroll:
- 比如
- 一般都需要将对象本身传出去
- 比如tableView的方法都会把tableView本身传出去
- 必须要遵守NSObject协议
- 比如
@protocol XMGWineCellDelegate <NSObject>
- 比如
- 协议名字的格式一般是:类名 + Delegate
- 声明一个代理属性
- 代理的类型格式:id<协议> delegate
@property (nonatomic, weak) id<XMGWineCellDelegate> delegate;
- 设置代理对象
xxx.delegate = yyy;
-
代理对象遵守协议,实现协议里面相应的方法
-
当控件内部发生了一些事情,就可以调用代理的代理方法通知代理
- 如果代理方法是@optional,那么需要判断方法是否有实现
if ([self.delegate respondsToSelector:@selector(wineCellDidClickPlusButton:)]) {
[self.delegate wineCellDidClickPlusButton:self];
}
iOS监听某些事件的方法
- 通知(NSNotificationCenter\NSNotification)
- 任何对象之间都可以传递消息
- 使用范围
- 1个对象可以发通知给N个对象
- 1个对象可以接受N个对象发出的通知
- 必须得保证通知的名字在发出和监听时是一致的
注册发布通知把自己传出去
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center postNotificationName:@"addButtonisBeClick" object:self userInfo:nil];
注册监听
- (void)viewDidLoad
{
[super viewDidLoad];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(clickAddButton:) name:@"addButtonisBeClick" object:nil];
}
方法实现
-(void)clickAddButton:(NSNotification *)note
{
DZwineCell *cell = note.object;
if (![self.wineIdex containsObject:cell.modle]) {
[self.wineIdex addObject:cell.modle];
}
int total = cell.modle.money.intValue + self.totalLable.text.intValue;
self.totalLable.text = [NSString stringWithFormat:@"%d",total];
}
KVO
- 仅仅是能监听对象属性的改变(灵活度不如通知和代理)
遍历数组取出字典模型
for (NSDictionary *dict in newArray) {
DZwineModle *modle = [DZwineModle wineModleWihtDic:dict];
//给每个模型一创建出来就添加一个监听
//KVO就是给对象自己添加一个监听
[modle addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
[arrayM addObject:modle];
}
注册后在销毁的时候一点要移除监听!!遍历添加几个移除几个!!
-(void)dealloc
{
for (DZwineModle *modle in self.wineArray)
{
[modle removeObserver:self forKeyPath:@"count"];
}
监听的方法要和注册的在一个文件中
warning 为什么会死循环!原因是因为一调用modle.count系统会检测出属性又开始改变了就又调用这个方法一检查值又是一样又反复调用,注意不要测试在这方法中改变原先要监听属性的值
-(void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(DZwineModle *)modle change:(nullable NSDictionary *)change context:(nullable void *)context
{
NSUInteger new = [change[@"new"] intValue];
NSUInteger old = [change[@"old"] intValue];
if (![self.wineIdex containsObject:modle]) {
[self.wineIdex addObject:modle];
// NSLog(@"%d",self.wineIdex.count);
}
if (new > old) {
int total = modle.money.intValue + self.totalLable.text.intValue;
self.totalLable.text = [NSString stringWithFormat:@"%d",total];
}else
{
int total = self.totalLable.text.intValue - modle.money.intValue;
self.totalLable.text = [NSString stringWithFormat:@"%d",total];
}
if (new == 0) {
[self.wineIdex removeObject:modle];
// modle.count = 1;
// NSLog(@"%d",self.wineIdex.count);
}
- 代理
- 使用范围
- 1个对象只能设置一个代理(假设这个对象只有1个代理属性)
- 1个对象能成为多个对象的代理
- 比
通知
规范 - 建议使用
代理
多于通知
- 使用范围
tabbleView的编辑
删除数据
-
先删除模型数据
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];```
-
在刷新对应行的数据
[self.mayTableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];
添加数据
- 先创建模型
DZtgModle *neWmodle = [[DZtgModle alloc]init];
neWmodle.title = modle.title;
neWmodle.icon = modle.icon;
[self.tgArray insertObject:neWmodle atIndex:0];
- 将模型添加到指定位置并刷新
NSIndexPath *path = [NSIndexPath indexPathForRow:0 inSection:0];
[self.mayTableView insertRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationLeft];
更新数据
- 取出指定模型,并且更改模型数据
DZtgModle *newModle = self.tgArray[0];
newModle.icon = modle.icon;
newModle.title = modle.title;
- 刷新指定位置的模型
NSIndexPath * path = [NSIndexPath indexPathForRow:0 inSection:0];
[self.mayTableView reloadRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationMiddle];
打开tableView的编辑模式
- 代开编辑模式
-(void)tableView:(nonnull UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(nonnull NSIndexPath *)indexPath
- 左滑按钮更改名字
-(NSString *)tableView:(nonnull UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
- 自定义多个按钮
- (nullable NSArray<UITableViewRowAction *> *)tableView:(nonnull UITableView *)tableView editActionsForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
UITableViewRowAction *action0 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"关注" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
NSLog(@"点击了关注");
// 收回左滑出现的按钮(退出编辑模式)
tableView.editing = NO;
}];
return @[action0];
}
批量删除
- 将选中的模型放到数组中
- (IBAction)deleMoreOjc:(id)sender {
NSArray *array =[self.mayTableView indexPathsForSelectedRows];
NSMutableArray *arrayM = [NSMutableArray array];
for (NSIndexPath *index in array) {
DZtgModle *modle = self.tgArray[index.row];
[arrayM addObject:modle];
}
[self.tgArray removeObjectsInArray:arrayM];
[self.mayTableView deleteRowsAtIndexPaths:array withRowAnimation:UITableViewRowAnimationLeft];
}
自定义批量删除
- 给模型定义一个bool属性标记
-(void)tableView:(nonnull UITableView *)tableView didDeselectRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
DZtgModle *modle = self.tgArray[indexPath.row];
// NSArray *array = [self.mayTableView indexPathsForSelectedRows];
modle.check = !modle.ischeck;
NSLog(@"%d",modle.check);
[tableView reloadData];
}