UI学习:多界面传值的正向传值(属性传值)和反向传值(代理传值)

文章目录

属性传值(正向传值)

正向传值 =从A界面→B界面传递数据

原理很简单:在B界面声明属性,A界面跳转前给属性赋值。

场景设置

A界面(VCFirst)有一个输入框,用户输入文字后跳转到B界面(VCSecond),B界面显示该文字。

第一步:创建两个ViewController

VCFirstVCSecond


第二步:在 VCSecond 中声明属性

objc 复制代码
// VCSecond.h

#import <UIKit/UIKit.h>

@interface VCSecond : UIViewController

// 声明一个属性,用来接收从A界面传过来的值
@property (nonatomic, copy) NSString *recievedText;

@end

关键点 :属性要声明在.h文件中,这样 VCFirst 才能访问到它。

第三步:VCSecond中使用传过来的值

objc 复制代码
// VCSecond.m

#import "VCSecond.h"

@interface VCSecond ()
@property (nonatomic, strong) UILabel *label;
@end

@implementation VCSecond

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    // 创建label显示传过来的文字
    self.label = [[UILabel alloc] initWithFrame:CGRectMake(100, 200, 200, 50)];
    self.label.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:self.label];
    
    //  在这里使用传过来的值
    self.label.text = self.recievedText;
}

@end

第四步:VCFirst中传值并跳转

objc 复制代码
// VCFirst.m

#import "VCFirst.h"
#import "VCSecond.h"  
@interface VCFirst ()
@property (nonatomic, strong) UITextField *textField;
@end

@implementation VCFirst

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    // 创建输入框
    self.textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 200, 200, 40)];
    self.textField.borderStyle = UITextBorderStyleRoundedRect;
    self.textField.placeholder = @"请输入内容";
    [self.view addSubview:self.textField];
    
    // 创建跳转按钮
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
    btn.frame = CGRectMake(100, 270, 200, 40);
    [btn setTitle:@"跳转到第二页" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
}

- (void)btnClick {
    // 1. 创建第二个控制器
    VCSecond *vc = [[VCSecond alloc] init];
    
    // 2. 核心:跳转前把值赋给B界面的属性
    vc.recievedText = self.textField.text;
    
    // 3. 跳转
    [self.navigationController pushViewController:vc animated:YES];
}
@end

代理传值 (反向传值)

反向传递值 =从B界面→A界面传递数据(返回时传递值)

属性传值做不到反向传值,因为A跳转到B时,A已经处于等待了,B无法直接访问A。

代理模式三要素:

要素 比喻
协议(Protocol) 规定"参与做某事"
代理人(代表) 真正做事的人(A界面)
委托方 发出请求的人(B界面)

场景设置

B界面有一个输入框,用户输入文字后点击返回,A界面的标签显示该文字。

第一步:在 VCSecond.h 中定义协议

objc 复制代码
// VCSecond.h

#import <UIKit/UIKit.h>

//  第一步:定义协议
@protocol VCSecondDelegate <NSObject>

// 协议方法:B界面需要传值时调用这个方法
- (void)vcSecond:(id)vcSecond didSendText:(NSString *)text;

@end


@interface VCSecond : UIViewController

//  第二步:声明delegate属性
// weak避免循环引用!代理属性必须用weak
@property (nonatomic, weak) id<VCSecondDelegate> delegate;

@end

代理属性必须用weak,避免A和B互相强引用导致内存泄漏。

第二步:VCSecond.m 中调用代理方法

objc 复制代码
// VCSecond.m

#import "VCSecond.h"

@interface VCSecond ()
@property (nonatomic, strong) UITextField *textField;
@end

@implementation VCSecond

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor orangeColor];
    
    // 输入框
    self.textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 200, 200, 40)];
    self.textField.borderStyle = UITextBorderStyleRoundedRect;
    self.textField.placeholder = @"输入要传回的内容";
    [self.view addSubview:self.textField];
    
    // 返回按钮
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
    btn.frame = CGRectMake(100, 270, 200, 40);
    [btn setTitle:@"返回并传值" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(backBtnClick) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
}

- (void)backBtnClick {
    //  核心:调用代理方法,把值传出去
    // 判断代理是否实现了该方法(安全写法)
    if ([self.delegate respondsToSelector:@selector(vcSecond:didSendText:)]) {
        [self.delegate vcSecond:self didSendText:self.textField.text];
    }
    
    // 返回上一页
    [self.navigationController popViewControllerAnimated:YES];
}

@end

第三步:VCFirst 遵守协议并实现方法

VCSecond 遵守协议

objc 复制代码
// VCFirst.h

#import <UIKit/UIKit.h>
#import "VCSecond.h"  //  导入,才能使用协议

//  遵守协议
@interface VCFirst : UIViewController <VCSecondDelegate>

@end

实现代理方法

objc 复制代码
// VCFirst.m

#import "VCFirst.h"

@interface VCFirst ()
@property (nonatomic, strong) UILabel *label;
@end

@implementation VCFirst

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    // 显示传回来的文字
    self.label = [[UILabel alloc] initWithFrame:CGRectMake(100, 200, 200, 50)];
    self.label.text = @"等待传值...";
    self.label.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:self.label];
    
    // 跳转按钮
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
    btn.frame = CGRectMake(100, 270, 200, 40);
    [btn setTitle:@"去第二页" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
}

- (void)btnClick {
    VCSecond *vc = [[VCSecond alloc] init];
    
    //  核心:设置代理为self(我来负责处理回调)
    vc.delegate = self;
    
    [self.navigationController pushViewController:vc animated:YES];
}

//  实现协议方法,接收B传回来的值
- (void)vcSecond:(id)vcSecond didSendText:(NSString *)text {
    self.label.text = text;
}

@end
相关推荐
云深处@11 小时前
【数据库】MySQL 入门
数据库·学习·mysql
HyperAI超神经11 小时前
【vLLM 学习】Disaggregated Prefill
人工智能·深度学习·学习·vllm
天吾cc11 小时前
RTT-IO设备模型
单片机·嵌入式硬件·学习
美味蛋炒饭.11 小时前
Git 版本控制(下)
开发语言·git·学习·总结·后端开发
呼噜想睡觉12 小时前
Bootstrap 组件之响应式导航条实现
学习
菜鸟‍12 小时前
【论文学习】Medical Image Analysis 2024 || 医学图像分割中失败检测方法的比较基准研究:揭示置信度聚合的作用
人工智能·学习
初级代码游戏13 小时前
iOS开发 Swift 速记7:结构体和类
开发语言·ios·swift
爱音乐的marlon13 小时前
FastAPI 学习笔记03|core 核心层:config 是总控制台,database 是整个工程的地基
笔记·学习·fastapi
math_hongfan15 小时前
鸿蒙离线数据缓存高级架构:弱网预加载/离线数据优先级/同步冲突解决/上线后数据合并策略
学习·缓存·华为·架构·harmonyos·鸿蒙
划水的code搬运工小李15 小时前
Simulink学习-自定义Storage Class配置
学习