【iOS】多界面传值

目录

属性传值(正向传值)

协议传值

通知传值

block传值

KVO传值


在iOS中的页面传值方式主要以下六种:

  1. 属性传值
  2. 单例传值
  3. NSUserDefault传值
  4. 代理传值
  5. block传值

属性传值(正向传值)

属性传值是通过定义属性并设置值来实现数据传递的方式,多用于前一个页面向后一个页面传值。

我们现在要跳转的第二个页面设置属性值

objectivec 复制代码
@property (nonatomic, strong) NSString *username;

在原来的页面创建B的实例,然后直接给他赋值,然后后一个页面就能拿到前一个页面的数值了

objectivec 复制代码
BViewController *bVC = [[BViewController alloc] init];
bVC.username = @"小明";
[self.navigationController pushViewController:bVC animated:YES];

在天气预报中,本人就使用了这种传值,效果如下

协议传值

协议传值是通过定义协议和代理方法,在不同页面之间传递数据。多用于后一个页面向前一个页面回传。在3gshare中,我们就假日详情页向首页传值就用到了这个。相当于上一个动图的反向。

我们先在需要传输信息的页面定义协议:其中包括需要传递的数据的代理方法

然后在发送数据的视图控制器的头文件声明代理属性,保存代理对象。

触发代理方法:

在发送数据的视图控制器中,在适当的时机,触发代理方法,并将需要传递的数据作为参数传递给代理方法

然后在接收的视图控制器中实现方法:

objectivec 复制代码
- (void)holidayDetail:(HolidayDetailViewController *)detail
  didChangeLikeStatus:(BOOL)isLiked
         newLikeCount:(NSInteger)likeCount
{
    NSMutableDictionary *item = [self.dataArray[0] mutableCopy];
    item[@"isLiked"] = @(isLiked);
    item[@"likeCount"] = @(likeCount);
    [self.dataArray replaceObjectAtIndex:0 withObject:item];
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1];
    [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}

最后把后面VC的代理设为前一个VC,让后一个为前一个代理。

通知传值

创建并发送通知:

首先,在发送者对象中创建一个通知,并指定通知的名称(通常使用字符串来表示)。可以通过NSNotification类或NSNotificationName宏来创建通知。需要传递信息给其他对象时,可以通过NSNotificationCenter的postNotificationName:object:userInfo:方法来发送通知。在发送通知时,可以附带一些额外的信息(如字典)作为通知的userInfo参数。

然后,我们需要注册观察者:

接收通知:

接收者对象需要实现一个方法,用于处理接收到的通知。这个方法是在观察者注册时通过selector参数指定的。当通知被发送时,通知中心会调用这个方法,并传递相关的信息给观察者。

最后,我们别忘了移除观察者,将其从通知中心移除,避免内存泄露。

block传值

在iOS开发中,可以使用Block(闭包)进行值的传递和回调操作。Block是一种封装了一段代码的对象,可以在需要的时候执行该代码块。

其基本步骤如下:

  1. 在后一个页面定义一个Block属性
objectivec 复制代码
@property (nonatomic, copy) void(^reutnblock)(NSString* temp, NSInteger num);
  1. 设置一个时间来触发返回上一级视图控制器的时候,使用第一步定义的block,把需要传递的放在^blcok中间
objectivec 复制代码
-(void)press{
    self.reutnblock(self.label.text, --_tag); // 重点部分
    [self.navigationController popViewControllerAnimated:YES];
    
}
  1. 在前一个页面跳转到后一个页面的事件函数中,调用后一个页面的Block这个属性
objectivec 复制代码
-(void)press {
    secondViewController* second = [[secondViewController alloc] init];
    second.reutnblock = ^(NSString * _Nonnull temp, NSInteger num) {
        self.label.text = temp;
        self.num = num;
    };
    [self.navigationController pushViewController:second animated:YES];
}

优点

Block提供了一种灵活的方式,可以封装一段代码并在需要的时候执行。这使得值传递的逻辑可以根据具体需求进行定制和扩展。

Block可以用于异步操作,例如在网络请求完成后执行回调操作。这样可以实现非阻塞的异步编程模式,提高代码的响应性和用户体验。

缺点

使用Block时,需要注意对循环引用和内存泄漏的处理。Block可能会持有其所捕获的变量和对象,如果不正确地处理循环引用,可能会导致内存泄漏。

较复杂的Block可能会导致代码变得难以理解和维护。由于Block可以封装任意代码逻辑,过度复杂或嵌套的Block可能会降低代码的可读性和可维护性。

block传值我目前还没在项目中实际使用过,以后在项目中的具体应用我会继续补充在博客中

KVO传值

概述

KVO全称KeyValueObserve也就是观察者模式,是apple提供的一套事件通知机制.允许对象监听另一个对应特殊属性的改变,并在改变时接受到该事件.一般继承自NSObject的对象都默认是支持KVO。

KVO(Key-Value-Observing,键值观察),即观察关键字的值的变化。首先在子页面中声明一个待观察的属性,在返回主页面之前修改该属性的值。在主页面中提前分配并初始化子页面,并且注册对子页面中对应属性的观察者。在从子页面返回主页面之前,通过修改观察者属性的值,在主页面中就能自动检测到这个改变,从而读取子页面的数据。KVO只对属性发生作用。

传递方向

主要也是从后往前。

1.注册观察者

objectivec 复制代码
@property (nonatomic, strong) secondViewController* second; //这里现在第一个页面中设置第二个页面作为自己的一个属性
- (void)press { //这里我才用了一个按钮来触发事件
    //[self willChangeValueForKey:@"ary"];
    self.second = [[secondViewController alloc] init];
    [self.second addObserver:self forKeyPath:@"userName" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    [self.navigationController pushViewController:self.second animated:YES];
}

observer: 这是观察者对象,即要接收属性变化通知的对象。通常是当前视图控制器或其他感兴趣的对象。

keyPath: 要监听的属性的名称,以字符串表示。当该属性的值发生变化时,KVO 就会通知观察者。

options: 一个枚举值,用于指定监听的选项。这个参数可以设置为多个选项的组合,使用按位或(|)进行连接。常见的选项有:

NSKeyValueObservingOptionNew: 当属性的值发生变化时,提供新的属性值作为通知的参数。

NSKeyValueObservingOptionOld: 当属性的值发生变化时,提供旧的属性值作为通知的参数。

NSKeyValueObservingOptionInitial: 在添加观察者时,立即发送一次通知,提供当前属性的值作为通知的参数。

NSKeyValueObservingOptionPrior: 在属性值发生实际变化之前,先发送一次通知,提供旧的属性值作为通知的参数。

context: 这是一个指针类型的参数,用于传递额外的上下文信息。通常情况下可以传入 NULL,表示不需要传递上下文信息。如果你需要在观察者中处理一些额外的信息,可以使用自定义的指针类型来传递数据。

2.实现监听方法

objectivec 复制代码
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"userName"]) {
        self.label.text = self.second.userName;
        NSLog(@"old text:%@   new text:%@", [change objectForKey:NSKeyValueChangeOldKey], [change objectForKey:NSKeyValueChangeNewKey]);
    }
}

3.移除观察者

objectivec 复制代码
- (void)dealloc {
    [self removeObserver:self forKeyPath:@"userName"];
}

tips

这种方式不可以实现对于数组元素的一个监听,因为KVO是对于setter方法的监听,而数组的addObject方法并不是setter方法的内容,所以无法通过上述方法实现对于数组的一个监听。

不使用时要移除KVO

相关推荐
MaoJiu1 天前
Flutter混合开发:在iOS工程中嵌入Flutter Module
flutter·ios
2501_915921431 天前
小团队如何高效完成 uni-app iOS 上架,从分工到工具组合的实战经验
android·ios·小程序·uni-app·cocoa·iphone·webview
2501_916008891 天前
uni-app iOS 文件管理与 itools 配合实战,多工具协作的完整流程
android·ios·小程序·https·uni-app·iphone·webview
Digitally1 天前
如何将视频从 iPhone 转移到 Mac
macos·ios·iphone
2501_916007471 天前
uni-app iOS 文件调试常见问题与解决方案:结合 itools、克魔、iMazing 的实战经验
android·ios·小程序·https·uni-app·iphone·webview
豆豆(设计前端)1 天前
使用 Uni-app 打包 外链地址APK 及 iOS 注意事项
ios·uni-app
库奇噜啦呼1 天前
属性关键字
ios
2501_915918411 天前
uni-app 项目 iOS 上架踩坑经验总结 从证书到审核的避坑指南
android·ios·小程序·https·uni-app·iphone·webview
游戏开发爱好者81 天前
iOS 上架 uni-app 流程全解析,从打包到发布的完整实践
android·ios·小程序·https·uni-app·iphone·webview