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

来源:互联网 发布:php 记录程序运行时间 编辑:程序博客网 时间:2024/05/22 19:46

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