ios面试

NSNotification、Block、Delegate和KV

2017-12-16  本文已影响0人  灵姝斐

iOS开发中数据传递的方法有很多种,我这里整理一下常用的NSNotification、Block、Delegate和KVO四种方式,仅供参考,具体使用要看开发中的需求,以及项目业务逻辑的需要.希望在适当的场景和业务下选择合适的方式去提高开发效率.

Block:

block是OC中一种对象和对象的通信方式,是一对一的关系.可以用于控制器与控制器的逆向传递数据。相比较代理而言的话,Block更加简洁灵活一点,不需要定义繁琐的协议方法,但通信事件比较多的话,建议使用Delegate;用block的话,一定要注意self的使用,防止循环引用导致的内存泄露.

用法:在a类中1,定义和2,回调block,在b类中3,实现block.

举例:
一, 按钮的触发事件.
1,定义block(有参数无返回值类型)

@property (nonatomic, copy) void(^didSelectDetailButton)(UIButton *sender);

2,block的回调.

- (void)pressDetailBtn:(UIButton *)sender{
  
    if (self.didSelectDetailButton) {
        self.didSelectDetailButton(sender);
    } 
}

3,block的具体实现.

   cell.didSelectDetailButton = ^(UIButton *sender) {
        
        SALookHaveSharedDetailController *haveVC = [SALookHaveSharedDetailController new];
        haveVC.dataArray = detailArray.mutableCopy;
        [weakSelf.navigationController pushViewController:haveVC animated:YES];
    };

二,block从后向前传值
1、在第二个视图控制器的.h文件中定义声明Block属性(block的定义):

//定义block
@property (nonatomic,copy) void (^NextViewControllerBlock)(NSString *tfText);

2, .m(block 的回调)

- (IBAction)BtnAction:(id)sender {
   
    //判断block是否为空
    if (self.NextViewControllerBlock) {
        self.NextViewControllerBlock(self.inputTF.text);
    }    [self.navigationController popViewControllerAnimated:YES];
}

3, 第一个控制器(block的实现)

- (IBAction)btnClicked:(id)sender {

NextViewController*nextVC =[[NextViewController alloc]init];
nextVC.NextViewControllerBlock= ^(NSString *tfText){ self.nextVCInfoLabel.text=tfText; }; [self.navigationController pushViewController:nextVC animated:YES];
}

代理:

delegate是是一对一的关系,通过setDelegate来设置代理对象,最典型的例子是常用的TableView.用代理的话,可以接收到调用协议方法的返回值,它定义的方法要按照一定的规范来写,这样易读性非常好,利于后期项目的维护以及修改。相比较而言代码量比较大.

用法:
在a类中1,定义代理和2,回调,在b类中3,指定代理对象4,遵循协议5,实现代理方法.

举例:
1,定义代理

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

@protocol SAAddJobPointRuleCellDelegate <NSObject>

- (void)tapAddJobPointRule:(SAAddJobPointRuleCell *)ruleCell;

@end

2,回调

- (void)tapAddAction:(UITapGestureRecognizer *)sender{
    
    if ([self.delegate respondsToSelector:@selector(tapAddJobPointRule:)]) {
        [self.delegate tapAddJobPointRule:self];
    }
}

3,指定代理对象

    self.cardSceneView.delegate = self;

4,遵循协议

@interface TestController ()<TestCardSceneViewDelegate>

5,实现代理方法

- (void)tapAddJobPointRule:(SAAddJobPointRuleCell *)ruleCell{
    self.isSelectReset = NO;
    SAGetAllShipperController *allVC = [SAGetAllShipperController new];
    allVC.selectIndex = ruleCell.cellIndex;
      [self.navigationController pushViewController:allVC animated:YES]; 
}

KVO:

KVO( Key-Value Observing),是Foundation框架提供的一种机制,可以一对多.使用KVO,可以方便地对指定对象的某个属性进行观察,(一个对象能够观察另外一个对象的属性的值,并且能够发现值的变化。)被观察的属性对应的对象 来 添加 和 移除 观察者.只能用来对属性作出反应,而不会用来对方法或者动作作出反应只负责把通知发出去,至于其他的事情就不管了,因此他们没有返回值.注意:我们观察的属性必须使用strings来定义.

用法:
1.由被观察的对象调用方法, 添加观察者:addObserver:forKeyPath:options:context:
2.一旦被观察的属性发生改变, 系统会调用这个方法:observeValueForKeyPath:ofObject:change:context:方法
3.解除观察者身份:removeObserver:forKeyPath:context:

举例:
1,定义属性:

@interface ShipperModel : NSObject

@property (nonatomic, copy) NSString *togetherString;

@property (nonatomic, copy) NSString *separateString;

@end

2,添加观察者

 [_shipperModel addObserver:self forKeyPath:@"togetherString" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
  [_shipperModel addObserver:self forKeyPath:@"separateString" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];

3,监测变化

#pragma mark -
#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { 
}

4,解除身份

- (void)dealloc {
   
    [self.shipperModel removeObserver:self forKeyPath:@"togetherString"];
    [self.shipperModel removeObserver:self forKeyPath:@"separateString"]; 
}

通知:

NSNotification是苹果提供的一种消息机制, 观察者只要向消息中心注册, 即可接受其他对象发送来的消息,消息发送者和消息接受者两者可以互相一无所知,完全解耦。NSNotification可以应用于任意时间和任何对象,可以一对多.但只负责把通知发出去,至于其他的事情就不管了,因此他们没有返回值

用法:a类中创建和移除通知,以及响应通知所要做的操作.b类通知中心发送通知
1,注册一个观察者
2,给通知中心发送一个消息
3,清除观察者

举例:
1,通知中心添加观察者

- (void)viewDidLoad {
    [super viewDidLoad];  
     [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(fifthStepAction:) name:@“fifthStep” object:nil];
}

2,响应通知所要做的事件操作.

//  object 和 userInfo可以带来想要接收的值
- (void)fifthStepAction:(NSNotification *)noti{
    
    NSDictionary *dict = noti.userInfo;
    self.isSettedSecondDismension = [dict[@"isSetted"] boolValue];
    self.typeName = dict[@"typeName"];
}

//- (void)fifthStepAction:(NSNotification *)noti{
    
//    self.isFromAddSureBack = [noti.object boolValue];
//}

3,移除通知

- (void)dealloc{
    [[NSNotificationCenter defaultCenter]removeObserver:self]; 
}

4,通知中心发送通知

// object 和 userInfo可以带来想要接收的值
  if (self.isTest) {
            NSNotification *noti = [[NSNotification alloc]initWithName:@“fifthStep”  object:nil userInfo:dict];
            [[NSNotificationCenter defaultCenter] postNotification:noti];
           
            [self.navigationController popToViewController:targetVC animated:YES]; 
        }
上一篇 下一篇

猜你喜欢

热点阅读