iOS 一一 自定义cell按钮的点击事件(KVO)

KVO :  Key Value Observing (键值监听)

当某个对象属性值发生改变的时候.可以使用KVO监听



代码如下:

ZYOperationButton文件

#import 

// 自定义按钮

@interface ZYOperationButton : UIButton

@end

@implementation ZYOperationButton

// 当从storyboard中或xib中加载完后会调用这个方法.\
    awakeFromNib是在viewDidLoad之前发生的。就是如果想要对view本身进行一些例如背景颜色,透明度之类的设置就只能在awakeFromNib里面进行,因为view被load之后再改就来不及了,所以只能在view被load之前进行设置,就是awakeFromNib。

- (void)awakeFromNib
{
    [super awakeFromNib];
    // 设置边框的宽度
    self.layer.borderWidth = 1.0f;
    // 设置边框颜色
    self.layer.borderColor = [UIColor orangeColor].CGColor;
    // 设置圆角半径
    self.layer.cornerRadius = self.frame.size.width * 0.5;
    
}

@end

ZYWine文件

#import 

@interface ZYWine : NSObject

/** 图片名 */
@property (nonatomic, copy) NSString *image;

/** 酒的名字 */
@property (nonatomic, copy) NSString *name;

/** 价格 */
@property (nonatomic, copy) NSString *money;

/** 购买数 */
@property(nonatomic,assign) int count;

@end

@implementation ZYWine

@end

ZYWineCell文件

#import 
@class ZYWine;
@interface ZYWineCell : UITableViewCell

/** 酒模型 */
@property(nonatomic,strong)ZYWine * wine;

@end

#import "ZYWine.h"
@interface ZYWineCell ()
@property (weak, nonatomic) IBOutlet UIImageView *icon;
@property (weak, nonatomic) IBOutlet UILabel *title_Label;
@property (weak, nonatomic) IBOutlet UILabel *price_Label;
/** 购买数 */
@property (weak, nonatomic) IBOutlet UILabel *buyCount;

@property (weak, nonatomic) IBOutlet UIButton *minusBtn;

@end

@implementation ZYWineCell

- (void)awakeFromNib
{
    [super awakeFromNib];
    // 当加载完storyboard的时候,把减号按钮设为不可点击
    self.minusBtn.enabled = NO;
    
}

- (void)setWine:(ZYWine *)wine
{
    // 通过酒数据模型设置数据
    _wine = wine;
    self.icon.image = [UIImage imageNamed:wine.image];
    self.title_Label.text = wine.name;
    self.price_Label.text = [NSString stringWithFormat:@"¥%@",wine.money];
    
    // 根据count决定buyCount显示的文字
    self.buyCount.text = [NSString stringWithFormat:@"%d",wine.count];
    
    // 根据count决定减号按钮是否能点击
    self.minusBtn.enabled = (wine.count > 0);
}

#pragma -mark 按钮点击事件
// 这样做的好处: 降低了耦合度,cell和控制器的关联不太大,如果在其他地方要使用到cell,监听cell的通知就可以了
- (IBAction)addBtnClick {
    
    //1. 当点击添加按钮,buyCount增加
    self.wine.count ++;
    
    //2. 修改界面(通过新的模型来修改界面)\
    因为在cell里面不能使用self.tableView reloadData 刷新数据\
    刷新数据的本质就是重新调用数据源方法,通过新的模型设置新的数据,既然如此,我们可以直接在内部通过\
    使用新的模型来设置数据
    self.buyCount.text = [NSString stringWithFormat:@"%d",self.wine.count];
    
    //3. 当点击添加按钮的时候,使减号按钮可以点击
    self.minusBtn.enabled = YES;
    
    
}

- (IBAction)minusBtnClick {
    
    //1.
    self.wine.count --;
    //2.
    self.buyCount.text = [NSString stringWithFormat:@"%d",self.wine.count];
    
    //3. 当buyCount为0,的时候,设置删除按钮为不可点
    if (self.wine.count == 0) {
        self.minusBtn.enabled = NO;
    }

}

@end


ViewController文件

#import 

@interface ViewController : UIViewController

@end

#import "ZYWineCell.h"
#import "MJExtension.h"
#import "ZYWine.h"

@interface ViewController () 

@property (weak, nonatomic) IBOutlet UITableView *tableView;

/** 装所有的酒模型的数组 */
@property (nonatomic,strong) NSArray *wineArray;

@property (weak, nonatomic) IBOutlet UILabel *totalPrice;

@property (weak, nonatomic) IBOutlet UIButton *buyButton;

@property (weak, nonatomic) IBOutlet UIButton *clearButton;
@end

@implementation ViewController
/**
    使用KVO不好的地方:
        > 当使用KVO的时候,不管在任何地方修改count的值,都会调用 observeValueForKeyPath:这个方法
        > 使用KVO来监听某个对象的属性,系统会默认为这个使用KVO的对象,在内部创建一个子类
 */
// 懒加载
- (NSArray *)wineArray
{
    if (_wineArray == nil) {
        _wineArray = [ZYWine mj_objectArrayWithFilename:@"wine.plist"];
        
        // 使用KVO,来监听wine的count属性,当count属性改变的时候,修改总价
        // 拿到所有的模型
        for (ZYWine *wine in _wineArray) {
            [wine addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
        }
        
    }
    return _wineArray;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    // 设置一开始没有购买的时候.清除购物车,购买按钮为不可点击
    self.clearButton.enabled = NO;
    self.buyButton.enabled = NO;
    
}

#pragma -mark KVO
// 当count属性发生改变就会调用这个方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(ZYWine *)wine change:(NSDictionary *)change context:(void *)context
{
    //1.通过改变count的内容来判断用户是点击的加号,还是减号按钮
    // 拿到新值,和 旧值
    //    NSLog(@"%@",change); // 通过change字典的new,old 这两个key,拿到对应的值
    // [NSKeyValueChangeNewKey == @"new"
    int new = [change[NSKeyValueChangeNewKey] intValue];
    // [NSKeyValueChangeOldKey == @"old"
    int old = [change[NSKeyValueChangeOldKey] intValue];
    
    //2. 根据new,old的大小来判断用户点击的加号按钮还是减号按钮
    if (new > old) {  // 加号按钮
        // 计算总价格(view上的价格 + 酒的价格)
        int totalMoney = self.totalPrice.text.intValue + wine.money.intValue;
        // 设置总价格(int类型转为NSString类型)
        self.totalPrice.text = [NSString stringWithFormat:@"%d",totalMoney];
        // 当监听到加号按钮点击的时候,设置buyButton,clearButton为可点击
        self.buyButton.enabled = YES;
        self.clearButton.enabled = YES;
        
    }else{   // 减号按钮
        // 计算总价格
        int totalMoney = self.totalPrice.text.intValue - wine.money.intValue;
        // 设置总价格(int类型转为NSString类型)
        self.totalPrice.text = [NSString stringWithFormat:@"%d",totalMoney];
        
        // 当监听到减号按钮点击的时候,设置buyButton,clearButton为可点击
        self.buyButton.enabled = totalMoney > 0;
        self.clearButton.enabled = totalMoney > 0;
    }
    
}

#pragma -mark 移除监听
- (void)dealloc
{
    for (ZYWine *wine in self.wineArray) {
        // 使用酒模型对象 移除 监听者控制器(self) 所监听的 count属性
        [wine removeObserver:self forKeyPath:@"count"];
    }
}

#pragma -mark 按钮的点击事件
- (IBAction)clearBtn {
    // 注意: 当使用KVO的时候,不管在任何地方修改count的值,都会调用 observeValueForKeyPath:这个方法,然后修改totalPrice的值.
    
    //2. 遍历所有的模型,把模型的count设为0
    for (ZYWine *wine in self.wineArray) {
        wine.count = 0;
    }
    
    //1. 把totalPrice设为0
    self.totalPrice.text = @"0";
    
    //3. 刷新表格
    [self.tableView reloadData];
    
    //4. 当点击清空购物车按钮后,设置buyButton,clearButton设为不可点击
    self.buyButton.enabled = NO;
    self.clearButton.enabled = NO;
    
}

- (IBAction)buyBtn {
    
    // 当点击购买按钮的时候.打印购买酒的信息
    for (ZYWine *wine in self.wineArray) {
        if (wine.count) { // 哪个数据模型的count不为0
            NSLog(@"您购买了%d瓶%@",wine.count,wine.name);
        }
    }
    
    
}
#pragma -mark  UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.wineArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID = @"wine";
    ZYWineCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    
    // 设置数据
    cell.wine = self.wineArray[indexPath.row];
    
    return cell;
}

@end



你可能感兴趣的:(iOS)