IOS——多界面传值

目录

一、属性传值

二、协议传值

 三、Block传值

 四、通知传值

五、KVO传值


一、属性传值

        属性传值适用于从前往后传。如果要从A往B传一个值,就首先在B界面的接口部分定义一个属性,然后在A界面创建一个B界面的实例对象,并给B的实例对象赋值并跳转视图控制器,这样我们赋的值就被传递给了B页面。

A界面实现部分:


- (void)pressGoB {
    B_ViewController *bView = [[B_ViewController alloc] init];
    bView.aToBStr = @"从A传来的值";
    [self.navigationController pushViewController:bView animated:YES];
}

B界面接口部分:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface B_ViewController : UIViewController

@property (nonatomic, copy) NSString *aToBStr;

@end

NS_ASSUME_NONNULL_END

B界面实现部分:

#import "B_ViewController.h"

@interface B_ViewController ()

@end

@implementation B_ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    UILabel *BLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 300, 200, 50)];
    BLabel.text = self.aToBStr;
    [self.view addSubview:BLabel];

}


@end

结果:

二、协议传值

        协议传值适用于从后往前传值。假设要从B视图往A视图传值,我们首先需要在B视图的接口部分定义一个协议并且为该协议添加一个方法,该方法的参数就是我们要传的值,然后添加代理者属性用于执行协议。然后在从B视图跳转到A视图的地方设定好代理 delegate的对象执行协议方法,最后在接收值的A界面遵循协议并且在A跳转到B的地方将B的代理者属性设定为A视图控制器,最后实现相应的协议方法即可。

B接口:定义协议、添加方法、创建代理者属性:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN


//创建协议
@protocol BToADelegate <NSObject>
//添加方法
- (void)BToAMode: (NSString*) bToAStr;

@end

@interface B_ViewController : UIViewController

@property (nonatomic, copy) NSString *aToBStr;

//设置代理者属性
@property (nonatomic, assign) id<BToADelegate> delegate;

@end

NS_ASSUME_NONNULL_END

B实现:设定好代理 delegate的对象执行协议方法 

- (void)pressGoA {
    //设定好代理 delegate的对象执行协议方法
    [self.delegate BToAMode:@"从B传来的值(协议)"];
    [self.navigationController popViewControllerAnimated:YES];
}

A接口:遵守协议

#import <UIKit/UIKit.h>
#import "B_ViewController.h"

NS_ASSUME_NONNULL_BEGIN

//遵守代理
@interface A_ViewController : UIViewController<BToADelegate>

@property (nonatomic, strong) UILabel *ALabel;

@end

NS_ASSUME_NONNULL_END

A实现:将B对象的代理者属性设置为A,并且实现相应的协议方法

//A跳转到B视图的函数
- (void)pressGoB {
    B_ViewController *bView = [[B_ViewController alloc] init];
    bView.aToBStr = @"从A传来的值";

    //将B对象的代理者属性设置为A
    bView.delegate = self;

    [self.navigationController pushViewController:bView animated:YES];
}

//协议方法,传来的bToAStr就是传来的值
- (void)BToAMode:(NSString *)bToAStr {
    self.ALabel.text = bToAStr;
}

结果:

 三、Block传值

        Block传值也是一种适用于从后往前传的传值方式,该方式的优点是相较于协议传值,它更简便。它传入的Block块本质上和其他变量一样,不过不同的是它存储的是一个函数体,我们可以直接在这个函数体中进行相应的赋值等操作。如果现在要从B向A传值,我们首先应该在B的接口部分声明一个Block属性,然后在由B跳转回A的位置将需要传递的值放入该属性的参数部分,最后在A跳转到B的位置调用B页面的Block属性,并在Block块中完成相应的操作。

B接口:声明Block属性:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN
//声明一个Block属性,传入两个参数
//第一个参数指Block块的返回类型,第二个参数指该Blcok块与其参数
typedef void (^BToABlock)(NSString *bToAStr);

@interface B_ViewController : UIViewController

@property (nonatomic, copy) NSString *aToBStr;

//声明属性
@property (nonatomic, strong) BToABlock bToABlock;

@end

NS_ASSUME_NONNULL_END

B实现:将需要传递的值放入该属性的参数部分:

- (void)pressGoA {
    //放入要传递的值
    self.bToABlock(@"从B传来的值(Block)");

    [self.navigationController popViewControllerAnimated:YES];
}

A实现:调用B对象的Block属性

- (void)pressGoB {
    B_ViewController *bView = [[B_ViewController alloc] init];
    bView.aToBStr = @"从A传来的值";

    //调用B对象的Block属性
    bView.bToABlock = ^(NSString *bToAStr) {
        self.ALabel.text = bToAStr;
    };

    [self.navigationController pushViewController:bView animated:YES];
}

结果:

 四、通知传值

        通知传值即可以从前往后传,也可以从后往前传值,并且该方法可以实现跨界面传值。使用通知传值一共有四个步骤,假设要在没有直接跳转关系的A和C两个界面间传值,若从C向A传值,首先需要在C界面实现一个方法发送通知,然后在A界面注册通知,也就是接收通知,最后在A界面实现通知中的方法即可。在不需要通知的地方要移除通知。

C实现:实现通知方法:

@interface C_ViewController ()

@end

@implementation C_ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
 
    NSDictionary *CToADictionary = [NSDictionary dictionaryWithObject:@"从C传来的值(通知)" forKey:@"label"];

    //通知方法
    [[NSNotificationCenter defaultCenter] postNotificationName:@"CToAString" object:nil userInfo:CToADictionary];
    //传入三个参数
    //第一个postNotificationName:该通知的名字,通知者和接收者的名字应该一样才能完成接收
    //第二个object:接收对象
    //第三个userInfo:通知携带的参数,该参数必须是一个字典对象,因此我们在传值之前应该定义一个字典并添加入我们要传的值
    
    
    UIButton *goAbutton = [UIButton buttonWithType:UIButtonTypeSystem];
    [goAbutton setTitle:@"返回到A界面" forState:UIControlStateNormal];
    goAbutton.frame = CGRectMake(100, 450, 100, 50);
    [goAbutton addTarget:self action:@selector(pressGoA) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:goAbutton];
}

- (void)pressGoA {
    [self.navigationController popToRootViewControllerAnimated:YES];
}

A实现:注册通知,并实现通知中的方法

#import "A_ViewController.h"
#import "B_ViewController.h"

@interface A_ViewController ()

@end

@implementation A_ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.ALabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 300, 200, 50)];
    [self.view addSubview:self.ALabel];
    
    UIButton *goBbutton = [UIButton buttonWithType:UIButtonTypeSystem];
    [goBbutton setTitle:@"跳转到B界面" forState:UIControlStateNormal];
    goBbutton.frame = CGRectMake(100, 450, 100, 50);
    [goBbutton addTarget:self action:@selector(pressGoB) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:goBbutton];
    
    //注册通知,该方法传入的name必须与通知者的name相同才能完成通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(CToAPress:) name:@"CToAString" object:nil];
    //CtoAPress:是我们要实现的方法
/*addObserver:selector:name:object: 是 NSNotificationCenter 类的方法,用于向通知中心注册观察者。
该方法接受四个参数:
1. observer:要注册的观察者对象,通常是调用该方法的实例对象。
2. selector:触发通知时要调用的方法,该方法在观察者对象中定义。它接受一个 NSNotification 对象作为唯一参数。
3. name:通知的名称,一个字符串,可以是自定义的或预定义的通知名称。
4. object:发送通知的对象。如果指定为 nil,则接收所有对象发送的通知;如果指定为特定对象,则只接收该对象发送的通知。*/

}

//该方法的参数是通知对象,在该方法中,我们要取值则需要调用此通知对象的userInfo属性,该属性就是我们传来的字典
- (void) CToAPress: (NSNotification*) sender {
    self.ALabel.text = sender.userInfo[@"label"];
}

在不用的时候要移除通知:

- (void)dealloc {
    //移除所有通知的方法:
    //[[NSNotificationCenter defaultCenter] removeObserver:self];
    
    //移除某个通知的方法:
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"TransDataNoti" object:nil];
}

结果:

​​​​​​​

五、KVO传值

        KVO全称Key Value Observing。KVO传值允许对象监听另一个对象的特定属性,当该属性改变的时候,会触发事件。

        KVO不仅可以监听单个属性的变化,也可以监听集合对象的变化。监听集合对象的时候,通过KVCmutableArrayValueForKey:等方法获得代理对象,当代理对象的内部对象发生改变时,会回调KVO监听的方法。集合对象包含NSArrayNSSet

        这里我们用一个案例来说明KVO传值:首先我们在A页面布局一个视图,再创建一个B类,该类只有一个age属性,然后再A页面通过KVO监听B类的age属性,并设置按钮改变B的age属性的值来触发监听方法,在监听方法中,对页面的label进行赋值。

A页面:

#import <UIKit/UIKit.h>
#import "AViewController.h"

@interface ViewController : UIViewController

@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) UIButton *button;
@property (nonatomic, strong) AViewController *aView;

@end
#import "ViewController.h"

@interface ViewController ()

@end

static int a = 0;
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    self.label = [[UILabel alloc] init];
    self.label.frame = CGRectMake(100, 200, 200, 80);
    [self.view addSubview:self.label];
    
    self.button = [UIButton buttonWithType:UIButtonTypeSystem];
    self.button.frame = CGRectMake(100, 400, 100, 80);
    [self.button setTitle:@"+1" forState:UIControlStateNormal];
    [self.button addTarget:self action:@selector(pressAdd) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.button];
    
    self.aView = [[AViewController alloc] init];
    //注册监听者
    //@observer:就是观察者,是谁想要观测对象的值的改变。
    //@keyPath:就是想要观察的对象属性。
    //@options:@options分为四个类型:
    //NSKeyValueObservingOptionNew 返回改变后的新值;NSKeyValueObservingOptionOld 返回改变之前的旧值;NSKeyValueObservingOptionInitial 注册的时候就会发一次通知,改变后也会发通知;NSKeyValueObservingOptionPrior 改变之前发一次通知,改变之后发一次通知
    //@context:想要携带的其他信息,比如一个字符串或者字典什么的,不过只能是同一视图的内容。
    [self.aView addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}

//实现UIButton的触发事件,用来触发监听
- (void)pressAdd {
    //改变aView中的age的值会调用监听方法
    self.aView.age = a++;
    NSLog(@"%d",self.aView.age);
}

//监听方法,当KVO事件到来的时候会调用这个方法
//@keyPath:观察的属性
//@object:观察的是哪个对象的属性
//@change:这是一个字典类型的值,通过键值对显示新的属性值和旧的属性值,新值的key是@"new",旧值的key是@"old"
//@context:上面添加观察者时携带的信息
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    //通过调用监听事件,来改变label显示的内容
    self.label.text = [NSString stringWithFormat:@"显示的数字是: %d",self.aView.age];
    //输出改变前的旧值和改变后的新值
    NSLog(@"旧值:%@,新值:%@",[change valueForKey:@"old"], [change valueForKey:@"new"]);
}

//在不使用的时候移除监听
- (void)dealloc {
    [self.aView removeObserver:self forKeyPath:@"age"];
}

@end

B类属性:

@interface AViewController : UIViewController

@property (nonatomic, assign) int age;

@end

结果:

​​​​​​​

点击+1后: 

注:

  • KVO只是监听setter方法,例如像可变数组添加元素的方法(addObject)它不属于setter方法,所以即使你向数组中add多少个元素也不会有监听反应。
  • 在不使用时一定要移除KVO。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
iOS中,可以通过WKWebView与JavaScript进行交互。以下是一些常见的方法: 1. 使用JavaScriptCore框架:在iOS 7及以上版本中,可以使用JavaScriptCore框架来实现WKWebView与JS的交互。具体实现步骤如下: (1)在iOS中创建一个JSContext实例,通过该实例可以操作JS环境。 (2)将JSContext实例设置到WKWebView的配置对象中。 (3)在JS中调用iOS方法时,可以通过window.webkit.messageHandlers对象进行调用,例如window.webkit.messageHandlers.methodName.postMessage(params)。 (4)在iOS中,可以通过WKScriptMessageHandler代理方法来接收JS递的消息,并进行处理。 2. 使用WKScriptMessageHandler协议:在iOS 8及以上版本中,可以通过WKScriptMessageHandler协议来实现WKWebView与JS的交互。具体实现步骤如下: (1)在WKWebView的配置对象中设置WKUserContentController的代理对象,并添加需要监听的JS方法名。 (2)在JS中调用iOS方法时,可以通过window.webkit.messageHandlers对象进行调用,例如window.webkit.messageHandlers.methodName.postMessage(params)。 (3)在iOS中,可以通过WKScriptMessageHandler代理方法来接收JS递的消息,并进行处理。 无论使用哪种方法,都需要注意JS和iOS之间递的数据类型和格式。通常,JS递的是字符串类型的数据,在iOS中需要进行解析和转换。同时,为了避免安全问题,需要对JS递的数据进行校验和过滤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值