OC语言多界面传值五大方式

前言

在完成暑假仿写项目时,遇到了许多需要用到多界面传值的地方,这篇博客来总结一下比较常用的五种多界面传值的方式。

属性传值

属性传值一般用前一个界面向后一个界面传值,简单地说就是通过访问后一个视图控制器的属性来为它赋值,通过这个属性来做到从前一个界面向后一个界面传值。

首先在后一个界面中定义属性

@interface BViewController : UIViewController

@property NSString* shuxingRecieved;

@end

然后在前一个界面中,当后一个界面要弹出时,为他的属性复制,这里以点击按钮触发事件为例,给出按钮事件中的代码

BViewController* bViewController = [[BViewController alloc] init];
self.data = @"我是要被传的";
bViewController.shuxingRecieved = self.data; //关键的一步
[self.navigationController pushViewController:bViewController animated:YES];

这样就可以实现属性传值了,一般用于从前向后传值

协议传值

协议传值一般适用于从后一个界面向前一个界面传值,本质上是通过协议中定义的方法来实现传值的,将后一个界面的值作为方法的参数,将参数赋给被传值界面的属性

首先在要传值的界面中定义一个用于传值的协议,并实现协议的方法,在这个方法中访问被传值界面的属性,并用方法的参数为属性赋值

@protocol xieyiPass 

- (void)xieyiPass:(NSString*)string;

@end

- (void)xieyiPass:(NSString*)string {
    self.xieyiRecieved = string;
    NSLog(@"%@", self.xieyiRecieved);
}

然后在要传值的界面设置代理,让这个代理遵守协议调用方法,这个代理其实也就是被传值的这个界面

//在被传值的界面中

//将子界面的代理设置为当前视图控制器
bViewController.delegate = self;


//在要传值的界面中

//定义代理属性
@property iddelegate;
//代理调用方法
[self.delegate xieyiPass:self.xieyidata];

这样就可以实现协议传值了,一般用于从后向前传值

通知传值

通知传值是一种常用于跨越两个以上界面之间的传值,就比如再写网易云音乐的夜间模式时,开关的改变要传递到分栏控制器的各个界面,再比如仿写天气预报时,添加城市后的数据,要从详情页跨过添加页直接传递到首页

首先介绍一下通知传值用到的类NSNotification

NSNotification这个类可以理解为一个用来存储消息的容器,他有三个属性:

@property (readonly, copy) NSString *name;

这个属性是这个消息对象的唯一标识,用于辨别消息对象。

@property (readonly, retain) id object;

这个属性定义一个对象,可以理解为针对某一个对象的消息。

@property (readonly, copy) NSDictionary *userInfo;

这个属性是一个字典,可以用其来进行传值。

需要注意的有两点:第一,如果定义了通知(消息)的对象,那么观察者接收到通知时,只有注册时定义的对象当前发送通知的对象一致时,观察者才能收到通知。但如果通知的对象设为nil,那么观察者就可以接收到任意对象发送的通知。

第二,观察者接收通知时调用的函数可以有一个参数,这个参数就是该通知本身就是,可以通过该通知来通知的userInfo,可以由此实现传值。

接下来讲解使用通知传值的过程:

第一步,创建并发送通知

可以通过NSNotification来发送通知。

NSDictionary* dictionay = [[NSDictionary alloc] init];
[[NSNotificationCenter defaultCenter] postNotificationName:@"notice" object:nil userInfo:dictionay];

第二步,注册观察者

观察者其实也就是被传值的对象,他在收到通知后执行一个方法,在这个方法中可以实现界面之间的传值。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(recieveNotice:) name:@"notice" object:nil];
}

 第三步,接收处理通知,这一步其实也就是实现当前界面需要实现的方法。

- (void)recieveNotice:(NSNotification*)send {
    self.tongzhidata = send.userInfo[@"key"];
}

第四步,移除观察者,但是现在的xcode好像已经可以自己对观察者进行dealloc操作了。

- (void)dealloc {
    // 移除通知观察者
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

 这样就可以实现通知传值了,一般用于跨越两个以上界面之间的传值。

block传值

block传值一般也用于从后一个界面向前一个界面传值,在暑假的五个项目中,没有用到block传值,对这种传值的知识还不太熟练,我的理解是这种传值就和协议传值类似,只是承载实现传值的那个方法的不是协议,而是一个block代码块。

第一步,在要传值的界面定义block属性

typedef void(^testblock) (NSString*);
@property testblock send;

 这里的typedef是为block起了一个别名,也就是textblock,后面的括号里是它的参数,这里表示这个block接收一个数据类型为NSString*的参数

第二步,为block提供参数,也就是将要传的值作为参数提供给block

_blockdata = @"我是block里要被传的";
self.send(self.blockdata);

第三步,在被传值界面设置block里的方法

BViewController* bViewController = [[BViewController alloc] init];
        bViewController.send = ^(NSString* sendtext) {
            self.blockRecieved = sendtext;
        };

这样就可以实现block传值了,block传值一般适用于从后一个界面向前一个界面传值 

KVO传值

KVO传值的全称是Key Value Observing,这是苹果提供的一套监听模式,可以监听某一个属性,当属性的值发生变化时(也就是调用setter方法时),观察者就会接收到方法并调用。

自动使用KVO传值

自动使用KVO传值主要有三个步骤:

第一步,注册观察者

[self addObserver:self forKeyPath:self.KVOdata options:NSKeyValueObservingOptionNew context:nil];

先解释一下这个方法各参数的含义:这里的Observer后面的参数就是要注册的观察者,KeyPath后面的参数是要监听的对象,options后面有几个选项:

NSKeyValueObservingOptionNew 返回改变后新的值

NSKeyValueObservingOptionOld 返回改变之前的旧值
NSKeyValueObservingOptionInitial 注册的时候就会发一次通知,改变后也会发通知
NSKeyValueObservingOptionPrior 改变之前发一次通知,改变之后发一次通知

第二步,实现监听方法

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSString* oldThing = [change valueForKey:NSKeyValueChangeOldKey];
    NSString* newThing = [change valueForKey:NSKeyValueChangeNewKey];
}

为观察者实现监听方法,这个监听方法在被观察的对象发生变化时会被调用,在这个方法中,我们经常使用NSValueChangeOldKeyNSKeyValueChangeNewKey这两个关键字和valueForKey的方法来获取被观察的对象变化前后的值。

第三步,移除观察者

[self removeObserver:self forKeyPath:self.KVOdata];

当观察者不再需要观察某个值时,需要调用该方法将观察者移除掉。

需要注意的是,这里的观察者只是在观察setter方法,也就是说当使用集合类时,为集合类增加元素(addObject:)等不涉及到setter的方法,不会触发KVO,这个时候就需要用到手动实现KVO。

注意⚠️:除了集合类,还有一些不是类的变量也无法自动触发KVO,比如C语言当中的一些基本数据类型

手动使用KVO传值

手动使用KVO传值的其他步骤都与自动使用KVO传值一模一样,只是在改变被观察对象时,需要手动提示当前被观察的对象在被发生改变,具体的代码如下:

[self addObserver:self forKeyPath:@"Array" options:NSKeyValueObservingOptionNew context:nil];
[self willChangeValueForKey:@"Array"];
[self.mutableArray addObject:@"啊这"];
[self didChangeValueForKey:@"Array"];

这里willChangeValueForKey和didChangeValueForKey通常成对出现,分别用来告诉观察者,被观察的对象即将要开始发生变化和变化已经完成。

总结

在这五大传值中,笔者暂时用的比较多的是属性传值、协议传值和通知传值,多界面传值的应用非常常见,一定要掌握好

你可能感兴趣的:(ios,ui,学习,objective-c,开发语言)