iOS开发-------自定义回调

这篇博客探讨了iOS开发中的自定义回调机制,包括目标-动作回调、委托回调和Block回调。作者通过实现一个KeyBoard类,展示了如何在count达到特定值时触发回调。通过对三种回调方式的讲解,帮助读者理解回调的原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       以前一直用系统写的类,比如UIButton,用到的时候我们只需要知道用addTarget方法来回调,产生动作,但是却不知道回调是如何产生的,通过学习,自己写了一个KeyBoard的类,大体运行结果就是,点击+1,内部有一个计数器count,会+1,当count=3的时候来进行回调,-1的时候,count - 1,=0的时候,count 制零,页面很简单,只需明白道理即可。

页面如下




目标-动作回调(Target-Action)

    首先创建一个叫做KeyBoard的类,具体操作也就不提了,相信都很熟,继承于UIView,因为我们所有的视图类几乎都是继承与UIView类,建好类之后,在我们的.m文件中添加两个属性,如下

//
//  Keyboard.m
//  自定义回调
//
//  Created by YueWen on 15/9/22.
//  Copyright (c) 2015年 YueWen. All rights reserved.
//

#import "Keyboard.h"

@interface Keyboard ()
{
    int _count;//计数器
}
@property(nonatomic,weak)id target;//目标(也就是谁进行的回调)
@property(nonatomic,assign)SEL action;//执行的目标的方法
@property (nonatomic,strong)UIButton *b1;
@property (nonatomic,strong)UIButton *b2;
@property (nonatomic,strong)UIButton *b3;

@end



接下来,用纯代码来布局button,但是button的创建费时费力,很不爽,所以封装了一个创建button的简易方法,相关功能也是可以再加的,这里需求少,所以简单
封装button的创建方法如下:
-(UIButton *)loadMyButtonWithTitle:(NSString *)title Tag:(int) tag
{
    UIButton * button = [UIButton buttonWithType:UIButtonTypeSystem];//初始化button
    button.translatesAutoresizingMaskIntoConstraints = NO;//解除Autoresizing布局
    [button setTitle:title forState:UIControlStateNormal];//设置button的文字
    button.tag = tag;//设置tag值
    [button addTarget:self action:@selector(tapButton:) forControlEvents:UIControlEventTouchUpInside];//实现按钮的目标动作回调
    return button;//返回实例化button的地址
}

实现手动布局以及初始化
@implementation Keyboard


//手动代码实例化keyboard时用的方法
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        
        [self otherInit];
    }
    return self;
}

//用xib或者storyboard创建的时候走这个方法
-(void)awakeFromNib
{
    [self otherInit];
}

//自己写的创建方法
-(void)otherInit
{
    //初始化按钮
    self.b1 = [self loadMyButtonWithTitle:@"+1" Tag:1];
    self.b2 = [self loadMyButtonWithTitle:@"-1" Tag:2];
    self.b3 = [self loadMyButtonWithTitle:@"=0" Tag:3];
    [self addSubview:self.b1];
    [self addSubview:self.b2];
    [self addSubview:self.b3];
    
    /**********开始布局*********/
    //水平布局
    NSArray * hArray = [NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"H:|-[_b1]-[_b2(==_b1)]-[_b3(==_b1)]-|"] options:0 metrics:nil views:NSDictionaryOfVariableBindings(_b1,_b2,_b3)];
    [self addConstraints:hArray];
    
    //b1垂直布局
    NSArray * vArray1 = [NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"V:|-20-[_b1]"] options:0 metrics:nil views:NSDictionaryOfVariableBindings(_b1)];
    [self addConstraints:vArray1];

    
    //b2垂直布局
    NSArray * vArray2 = [NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"V:|-20-[_b2]"] options:0 metrics:nil views:NSDictionaryOfVariableBindings(_b2)];
    [self addConstraints:vArray2];

    
    //b3垂直布局
    NSArray * vArray3 = [NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"V:|-20-[_b3]"] options:0 metrics:nil views:NSDictionaryOfVariableBindings(_b3)];
    [self addConstraints:vArray3];
  
    
    
}

接下来为了方便UI设置,用了storyboard,拖一个View放到ViewController,并设置好约束之后,


不要忘记的是,给拖进去的View绑定我们写好的keyboard类


接下来就要启动按钮的回调了
首先将我们的方法在.h文件中写好,方便外调,目标动作回调方法如下:
//添加目标动作回调的方法
-(void)addTarget:(id)target action:(SEL)action;

实现它
-(void)addTarget:(id)target action:(SEL)action
{
    self.target = target;
    self.action = action;
}

button的回调放入如下
//    目标动作回调   
-(void)tapButton:(UIButton *)button
{
    if (button.tag == 1)//如果是+1按钮被点击
    {
        _count ++;
        
        if (_count == 3)//如果计数器=3
        {
            //target对象执行他的action方法
            [self.target performSelector:self.action withObject:self];
            
            _count = 0;
        }
    }
    else if (button.tag == 2)
    {
        _count --;
    }
    else if (button.tag == 3)
    {
        _count = 0;
    }
    
    NSLog(@"count = %d",_count);
}

最后需要在ViewController中将view拖到Controller中,并且给keyboard添加目标动作回调,如下
#import "ViewController.h"
#import "Keyboard.h"

@interface ViewController ()

@property (strong, nonatomic) IBOutlet Keyboard *kb;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self.kb addTarget:self action:@selector(myCount)];//添加目标动作回调


}

-(void)myCount
{
    NSLog(@"目标动作回调了!");
}

当点击三下+1的时候,结果如下,证明keyboard进行了自己的目标动作回调



委托回调(Delegate)

   若想进行委托回调,那么必然会有协议的生成,楼主比较喜欢将协议写在.h文件中,在原基础上修改,并不需要修改很多,话不多讲,头文件以及协议如下:
#import <UIKit/UIKit.h>
@protocol keyboardDelegate;
@interface Keyboard : UIView

@property(nonatomic,weak)id<keyboardDelegate>delegate;//设置代理对象属性

@end

@protocol keyboardDelegate <NSObject>

@optional//可选的

-(void)keyboardCount:(Keyboard *)keyboard;//协议方法

@end

在实现文件中,只需要更改一下按钮回调方法,改正如下
//委托回调
-(void)tapButton:(UIButton *)button
{
    if (button.tag == 1)
    {
        _count ++;
        
        if (_count == 3)
        {
            //首先判断代理对象是否有协议方法,如果没有这句话,会崩
            if ([self.delegate respondsToSelector:@selector(keyboardCount:)])
            {
                //如果有,执行该协议方法
                [self.delegate keyboardCount:self];
            }
            
            _count = 0;
        }
    }
    else if (button.tag == 2)
    {
        _count --;
    }
    else if (button.tag == 3)
    {
        _count = 0;
    }
    
    NSLog(@"count = %d",_count);
}

最后在Controller中,实现代理
#import "ViewController.h"
#import "Keyboard.h"

@interface ViewController ()<keyboardDelegate>//不要忘记履行协议

@property (strong, nonatomic) IBOutlet Keyboard *kb;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.kb.delegate = self;

}

//实现协议方法
-(void)keyboardCount:(Keyboard *)keyboard
{
    NSLog(@"我是委托回调方法!");
}


当点击三下+1的时候,结果如下,证明keyboard进行了自己的委托回调,委托回调比目标动作回调的优势就在于,它可以传递参数,而目标动作回调却无法传递参数


Block(代码块)回调

代码块相比于上面两种回调方法,显得更简洁,容易,首先在Keyboard.h中定义代码块,如下
#import <UIKit/UIKit.h>

typedef void(^KBM)(void);//定义代码块,无返回值无参

-(void)setBlockB:(KBM)b;//设置代码块的方法

是不是头文件中很干净呢,接下来就是实现文件
@property(nonatomic,strong)KBM b;//通过延展给keyboard增加一个代码块属性

实现给代码块赋值的方法
//给代码块赋值的方法
-(void)setBlockB:(KBM)b
{
    self.b = b;
}

接下来就是按钮的回调方法了,在稍作修改
//block回调
-(void)tapButton:(UIButton *)button
{
    if (button.tag == 1)
    {
        _count ++;
        
        if (_count == 3)
        {
            self.b();//执行代码块里面的内容
            _count = 0;
        }
    }
    else if (button.tag == 2)
    {
        _count --;
    }
    else if (button.tag == 3)
    {
        _count = 0;
    }
    
    NSLog(@"count = %d",_count);
}

最后在ViewController中写入代码块b中的内容
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self.kb setBlockB:^{
       
        NSLog(@"我是Block回调!");
        
    }];
    
}


当点击三下+1的时候,结果如下,证明keyboard进行了自己的Block回调





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值