做iOS开发应该都头疼过这样一个问题:跨页面回调数据!
假设有这样一个场景:
三个viewController依次被push出来,简称A、B、C三个页面。
其实C页面的操作会影响A页面的某项展示,而push出的页面,正常情况下我们会一级级pop回去,当我们pop两次之后回到A的时候发现数据还是原始数据,这肯定是不太友好的。那么我们就需要知道在C页面进行了什么骚操作,进行必要的更新。要么拉取服务端数据要么改值,终归要知道C页面里做没做,此时我们可以用 通知 进行传值,可以跨多层直到目标,但是一个较大的项目中若滥用通知的话视乎有点可耻。
还有另外两种方式:代理 block。但是跨页面的时候难免会有这么一层传递。
🌰例如:
// C 页面这么写
- (void)XXXX事件:(id)sender{
if (self.delegate && [self.delegate respondsToSelector:@selector(XXXX代理方法:)]) {
[self.delegate XXXX代理方法:obj];
}
}
// B页面自己再声明一个protocol,并声明一个属性 同时遵守C声明的协议并实其delegate方法
- (void)C页面代理方法:(id)obj{
// 在C页面的代理方法里调自己的代理方法
if (self.delegate && [self.delegate respondsToSelector:@selector(XXXX代理方法:)]) {
[self.delegate XXXX代理方法:obj];
}
}
// A页面遵守B协议并实现代理
- (void)B页面代理方法:(id)obj{
// 拿到C回调过来的值 进行一些处理
}
🔥如此一套下来,总看着B页面里的delegate那么多余,就做了如下设想:
既然目的只是让A拿到C的回调,那么我是否可以不在B里声明一套自己协议呢?做了如下尝试:
C页面.h头文件
#import <UIKit/UIKit.h>
@protocol testDelegateTransition <NSObject>
- (void)callBackSomeContent:(id)obj;
@end
@interface ViewControllerC : UIViewController
@property (nonatomic, weak) id <testDelegateTransition> delegate;
@end
B页面.h文件
#import <UIKit/UIKit.h>
// 为了引用C页面的testDelegateTransition 只能先import其头文件
#import "ViewControllerC.h"
@interface ViewControllerB : UIViewController
@property (nonatomic, weak) id <testDelegateTransition> delegate;
@end
B页面.m实现文件
@implementation TestTransDelegateVCB
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.navigationItem.title = @"代理传递的中专页面";
self.view.backgroundColor = [UIColor purpleColor];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
TestTransDelegateVCD *vc = [[TestTransDelegateVCD alloc] init];
vc.delegate = self.delegateB;
[self.navigationController pushViewController:vc animated:YES];
}
@end
VCA的.m文件
#import "ViewControllerA.h"
#import "ViewControllerB.h"
@interface ViewControllerA ()<testDelegateTransition>
@end
@implementation TestTransDelegateVCA
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"测试代理传递";
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
ViewControllerB *vc = [[ViewControllerB alloc] init];
vc.delegateB = self;
[self.navigationController pushViewController:vc animated:YES];
}
// C页面的代理方法
- (void)callBackSomeContent:(id)obj{
}
@end
😊很开心,此次尝试成功的,说明想法没问题,也没有影响VC的释放。那么有没有别的问题呢?🎈还是有点的,比如没必要在VCB的.h头文件里就导入C。接着进行点整理,把delegate声明相关放在创建的单独的头文件。
#ifndef TestTransitionDelegateHeader_h
#define TestTransitionDelegateHeader_h
@protocol testDelegateTransition <NSObject>
- (void)callBackAContent:(NSString *)c;
@end
#endif /* TestTransitionDelegateHeader_h */
这样,因为需要访问这个delegate而导入的ViewControllerC就可以省掉,转而导入TestTransitionDelegateHeader_h这个头文件。
这一次设想到此就验证结束了,涉及的7个文件可以到 这里 查看。里边有我所有的猜想验证、demo、小测试。
🤣说了半天废话其实就这么一句话:"简化了 B页面里边,声明自己协议 遵守C协议并实现方法 ";
网友评论