Effective Objective-C 2.0 学习记录(三)

Effective Objective-C 2.0 学习记录(一)
Effective Objective-C 2.0 学习记录(二)

十一、协议(protocol)与分类(category)
我们可以把某个类应该实现的一系列方法定义在协议里面,最为常见的用途就是实现委托(delegate)模式
利用分类我们无须继承子类就可以为当前类添加方法。

1、delegate例子:(当然也可以用block,kvo/kvc,notification)
我们实现一个简单的功能,在当前页面A(ViewController)有个Label,显示一段文字,点击按钮进入下一个页面B(NextViewController),在页面B中有个Label,点击按钮返回页面A,此时页面A中的Label的文本内容改为B中Label的内容。

A页面中:

//.h文件
#import <UIKit/UIKit.h>
#import "NextViewController.h"

@interface ViewController : UIViewController<YCFShowContentDelegate>

@property (nonatomic, strong) UILabel *showLabel;

@end

//.m文件
- (void)viewDidLoad {
    [super viewDidLoad];

   //进入下个页面按钮
    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, 100, 30)];
    [btn addTarget:self action:@selector(onClickBtn) forControlEvents:UIControlEventTouchUpInside];
    btn.backgroundColor = [UIColor redColor];
    [self.view addSubview:btn];

    _showLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, 30)];
    _showLabel.text = @"A 中 Hello world";

    [self.view addSubview:self.showLabel];

}

- (void)onClickBtn {

    NextViewController *ycf = [[NextViewController alloc] init];
    ycf.delegate = self;//一定要写,否则回调不会执行
    [self presentViewController:ycf animated:YES completion:nil];
}
//delegate回调
- (void)showContent:(NSString *)content{
    _showLabel.text = content;
}

B页面中:

//.h文件
#import <UIKit/UIKit.h>
@protocol YCFShowContentDelegate <NSObject>
//对于委托实现的方法我们可以用optional来修饰,告知被委托的页面,并不是所有的方法都要实现,都则会有警告告知用户又些委托方法没有实现。对于有强迫症的大大来说,这样解决是最好了。
@optional
- (void)showContent:(NSString *)content;

@optional
- (void)reLoadCurrentVC;

@end

@interface NextViewController : UIViewController

@property (nonatomic, weak) id <YCFShowContentDelegate> delegate;

@end

//.m文件
#import "NextViewController.h"

@interface NextViewController (){

    UILabel *showLabel;
}

@end

@implementation NextViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor whiteColor];

    showLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, 30)];
    showLabel.text = @"this is next viewcontroller!";

    [self.view addSubview:showLabel];


    UIButton *changeBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, 60, 40)];
    [changeBtn setTitle:@"返回显示label内容" forState:UIControlStateNormal];
    changeBtn.backgroundColor = [UIColor lightGrayColor];
    [changeBtn addTarget:self action:@selector(onClickBtn) forControlEvents:UIControlEventTouchUpInside];
    [changeBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [self.view addSubview:changeBtn];

}

- (void)onClickBtn{
    //在这里一定要判断下,是否被委托的页面实现了该方法,不判断的话程序会crash。
    if (_delegate && [_delegate respondsToSelector:@selector(showContent:)]) {

        [_delegate showContent:showLabel.text];
    }

    [self dismissViewControllerAnimated:YES completion:nil];
}

2、category:通过分类机制,可以把类代码分成很多个易于管理的小块,便于调试,不过在需要使用的地方要引入分类的头文件。
记得面试时,问过一个问题:在项目中,有很多网络请求的数据,但是有可能服务端对数据没有进行设置,又些数据为空,到客户端要是没有处理,直接取值,程序可能会crash,用一种方法来防止在这种情况下程序的crash。
虽然在每个关于网络取值的地方我们每取一个值就进行判断,但是页面多,每次都要判断,不方便。我们可以为NSArray写个categroy。

1)、新建一个catorgy
新建一个catorgy

2)、写一个判断取值的方法,把会crash的情况考虑到

//.h文件
@interface NSArray (YCFKeepIndexSafe)


- (id)ycf_objectIndexCheck:(NSUInteger)index;

@end

//.m文件
- (id)ycf_objectIndexCheck:(NSUInteger)index{

    if (index >= self.count) {

        return nil;//如果不想在页面上显示“null”,则可以返回@"";
    }

    id value = [self objectAtIndex:index];

    if (value == [NSNull null]) {
        return nil;//如果不想在页面上显示“null”,则可以返回@"";
    }
    return value;
}

我们在一个VC中测试下:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSArray *arrList = [[NSArray alloc] initWithObjects:@"Sam",@"Yuna",,@"Vernal", nil];
    NSLog(@"%@",[arrList ycf_objectIndexCheck:4]);//此时不会crash
}

注意:我们在给分类中添加方法的时候,方法名加上前缀是为了防止方法名重复。引起不必要的bug。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值