[ios development] Implementation and comparison of commonly used value passing methods

1. The realization process of KVO, notification, proxy transfer and block transfer

All four are completed through a simple demo of login and registration

1. Block transfer value

Operation method

1 Get an alias for the block, and write the parameters that need to be passed in the parameter list to set the block attribute (note the use of copy)

2 Set up a method (such as the button click event method) to pass the value that needs to be passed when the current block is held

3 Call the block side where the object is created

Source code

//在需要传值的第二界面的.h
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface RegisterViewController : UIViewController

@property (nonatomic, strong) UITextField *renameTextField;
@property (nonatomic, strong) UITextField *repassTextField;

@property (nonatomic, strong) UIButton *relandButton;

@property (nonatomic, copy) void (^testBlock) (NSString *name, NSString *pass);

@end

NS_ASSUME_NONNULL_END

//第二界面.m文件 上面的viewDidLoad中间的内容就是创建视图的位置 后面的按钮点击事件的方法则持有block并且负责赋值
-(void)back{
    
    
    _testBlock(_renameTextField.text,_repassTextField.text);
    [self dismissViewControllerAnimated:YES completion:nil];
}
@end
//第一界面的viewcontroller负责在创建该对象的地方进行调用
-(void)press{
    
    
    RegisterViewController *view = [[RegisterViewController alloc]init];
    
    view.testBlock = ^(NSString *name,NSString *pass){
    
    
        self->_nameTextField.text = name;
        self->_passTextField.text = pass;
    };
    [self presentViewController:view animated:YES completion:nil];
}

Two, proxy value transfer

1. Set the informal protocol
in the second-level controller .h file 2. Write the attributes and methods
in the protocol in the second-level controller .h file 3. In the second-level controller .m file, use Agent attribute, to call the method in the protocol (pass the parameters at the same time)
4. Follow the protocol
in the first-level controller 5. Set the agent
in the first-level controller 6. Rewrite the agent in the first-level controller method



//二级控制器.h文件
#import <UIKit/UIKit.h>
//第一步设置协议 protocol就是协议的意思 p2:自己设置这个协议的名字 p3:后面挂个NSObject
@protocol TestDelegate <NSObject>

-(void)pass:(NSString *_Nullable)name and:(NSString *_Nullable)pass;
@end
NS_ASSUME_NONNULL_BEGIN
@interface RegisterViewController : UIViewController

@property (nonatomic, strong) UITextField *renameTextField;
@property (nonatomic, strong) UITextField *repassTextField;

@property (nonatomic, strong) UIButton *relandButton;

@property (nonatomic, weak) id <TestDelegate> registerDelegate;

@end

NS_ASSUME_NONNULL_END
//二级控制器.m文件 在点击事件中,利用代理属性给协议里的方法两个参数赋值
-(void)back{
    
    
    [_registerDelegate pass:_renameTextField.text and:_repassTextField.text];
    [self dismissViewControllerAnimated:YES completion:nil];
}

//一级控制器先要设置代理	然后通过代理中的方法进行参数值的传递

//直接调用方法进行赋值即可
-(void)pass:(NSString *)name and:(NSString *)pass{
    
    
    _nameTextField.text = name;
    _passTextField.text = pass;
}
-(void)press{
    
    
    RegisterViewController *view = [[RegisterViewController alloc]init];
    //设置代理
    view.registerDelegate = self;
    [self presentViewController:view animated:YES completion:nil];
}

Three, notification transfer value

1 Create a notification object in the button click event in the second-level controller .m file, pass in the two values ​​registered in the login, and then send the notification to the message center.
2 Register in viewWillAppear in the first-level controller .m file Notification (Add an observer to specify a method, name or object, and execute the specified method when the notification is received.)
3 Assign data in the calling method
4 Remove the observer ( Why remove the observer? )

//第二级视图控制器.m文件
-(void)back{
    
    
    
    //1.创建通知对象
    NSNotification *noti = [NSNotification notificationWithName:@"send" object:self userInfo:@{
    
    @"name":_renameTextField.text,@"pass":_repassTextField.text}];

    //2.通知中心去发布通知
    [[NSNotificationCenter defaultCenter] postNotification:noti];
       
    [self dismissViewControllerAnimated:YES completion:nil];
}

//第一级控制器的.m文件

- (void)viewWillAppear:(BOOL)animated {
    
    
    [super viewWillAppear:animated];
    //3.注册通知 添加观察者来指定一个方法、名称和对象,接受到通知时执行这个指定的方法。
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(recive:) name:@"send" object:nil];
}

//4.接收通知后调用的方法
- (void)recive:(NSNotification *)noti {
    
    
    NSDictionary *dic = noti.userInfo;
    _nameTextField.text = dic[@"name"];
    _passTextField.text = dic[@"pass"];
}

-(void)dealloc{
    
    

[[NSNotificationCenter defaultCenter] removeObserver:self];
}


Four, KVO

Registering Observer
Usage: addObserver:forKeyPath:options:context:
Parameter meaning:
1. Observer: Observer, the object that monitors property changes. The object must implement the observeValueForKeyPath:ofObject:change:context: method.
2. keyPath: The name of the attribute to be observed. Must be consistent with the name of the attribute declaration.
3. options: configure the KVO mechanism, modify the timing of the KVO notification and the content of the notification
4. context: pass in any type of object, which can be received in the code of "receive message callback", which is one of KVO A way of passing values.
options parameter:
enum { NSKeyValueObservingOptionNew = 0x01, NSKeyValueObservingOptionOld = 0x02, NSKeyValueObservingOptionInitial = 0x04, NSKeyValueObservingOptionPrior = 0x08 }; typedef NSUInteger NSKeyValueObservingOptions: the new value of NSKeyValueObservingOptions: the new value of the new value received by the method is accepted by default . NSKeyValueChangeNewKey;








NSKeyValueObservingOptionOld: Use the change parameter to pass in the old value before the change in the receiving method. The key is: NSKeyValueChangeOldKey;
NSKeyValueObservingOptionInitial: The receiving method is called immediately after registration. If NSKeyValueObservingOptionNew is configured, the change parameter content will contain the new value, the key is: NSKeyValueChangeNewKey;
NSKeyValueObservingOptionPrior: If this parameter is added, the receiving method will be called once before and after the change, two times in total. The change parameter of the notification before the change contains notificationIsPrior = 1.

Receive notification How to
use: observeValueForKeyPath:ofObject:change:context:

Cancel registration
Usage: removeObserver:forKeyPath:context

Specific part of the code:

//第一级页面.m文件添加一个指向第二级视图的成员变量
@property (nonatomic, strong) RegisterViewController *secondView;
//按下按钮跳转界面添加下面
-(void)press{
    
    
    _secondView = [[RegisterViewController alloc]init];
      [_secondView addObserver:self forKeyPath:@"strNameWord" options:NSKeyValueObservingOptionNew context:nil];
      [_secondView addObserver:self forKeyPath:@"strPassWord" options:NSKeyValueObservingOptionNew context:nil];
    [self presentViewController:_secondView animated:YES completion:nil];
}
//接收与移除
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    
    
    
     if ([keyPath isEqualToString:@"strNameWord"]) {
    
    
         _nameTextField.text = _secondView.strNameWord;
       }
    if ([keyPath isEqualToString:@"strPassWord"]) {
    
    
        _passTextField.text = _secondView.strPassWord;
      }
    
}
- (void)dealloc
{
    
    
    [_secondView removeObserver:self forKeyPath:@"userName"];
    [_secondView removeObserver:self forKeyPath:@"userPass"];
}



//第二级视图.h
//添加两个被观察的对象
@property (nonatomic, strong) NSString *strNameWord;
@property (nonatomic, strong) NSString *strPassWord;

//下面为正常的三个
@property (nonatomic, strong) UITextField *renameTextField;
@property (nonatomic, strong) UITextField *repassTextField;
@property (nonatomic, strong) UIButton *relandButton;




//按下时跳转页面并且修改值就行了
-(void)back{
    
    
    self.strNameWord = self.renameTextField.text;
    self.strPassWord = self.repassTextField.text;
    [self dismissViewControllerAnimated:YES completion:nil];
}



Some of the above process is not understood, refer to this blog: ( The way of passing values ​​between iOS pages )

2. Comparison of several kinds of value passing

A simple summary of 4 ways of passing values ​​is realized through this demo:

1. The difference between agency and notification

Efficiency: Agency is higher than notification;
Association: delegate is a strong association, and both parties know each other. The notification is weakly related, and there is no need to know who sent it or who received it.
The agent is a one-to-one relationship, and the notification is a one-to-many relationship. Delegate generally requires others to complete the behavior. The notification is a global notification.
The agent can send messages to multiple classes by adding the agent to the collection class and then traversing, or by message forwarding.

2. The difference between KVO and notification

The same: it is a one-to-many relationship; the
difference: the notification requires the observer to actively send out the notification, and the observer registers to listen and then responds. There is more than the KVO to send the notification.
Monitoring range: KVO is to monitor a value change. Notification is not limited to monitoring the changes of attributes, but can also monitor a variety of state changes, with a wide monitoring range and more flexible use.
Usage scenario: The general usage scenario of KVO is to monitor data changes, and the notification is a global notification.

3. The difference between block and proxy

The same point: both block and proxy are callback methods. The usage scenarios are the same.

difference:

Block centralizes code blocks, while agents decentralize code blocks. So block is more suitable for light and simple callbacks, such as network transmission. Proxies are suitable for situations where there are many public interfaces, which makes it easier to decouple the code architecture.
Block operation cost is high. When the block is popped from the stack, it is necessary to copy the used data from the stack memory to the heap memory. Of course, if it is an object, it will count up, and it will be eliminated after use or block is set to nil. The agent just saves an object pointer and calls back directly without additional consumption. Compared with the C function pointer, it just does an extra lookup action.

Guess you like

Origin blog.csdn.net/m0_46110288/article/details/108652393