版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/blog_DreamFly/article/details/79401306
常见的有6种,可分为正向传值、反向传值、跨界面传值;
1.属性
只适用于正向传值,A页面跳转到B页面;
在A控制器界面中
BViewController *vc = [BViewController alloct] init];
vc.title = @"需要传递的值";
2.单例
即可以正向传值、也可以反向传值、又能跨界面传值;
单例类只需实例化一次,有且仅有一个单例对象;
OC中常见的单例类:
- AppDelegate
- NSUserDefaults
- NSNotification
- NSFileManager
3.代理传值
反向传值,B页面跳转回A页面;
组成部分:
- 委托方:规定协议内容,持有协议;
- 代理方:遵守协议,并实现协议方法;
- 协议:通信规则,委托方和代理方通信的纽带;
声明协议的关键字是@protocol,修饰协议方法的关键字:
@required:必须实现的方法 ;
@optional:可实现、可不实现的的方法;
(1).在B控制器界面.h文件中,声明自己的协议;
@protocol BViewControllerDelegate <NSObject>
- (void)sendUsername:(NSString *)username password:(NSString *)password;
@end
@interface BViewController : UIViewController
// 声明属性,注意weak修饰
@property (nonatomic, weak) id <BViewControllerDelegate> delegate;
@end
在B控制器界面.m文件中
// 赋值
[self sendUsername:_usernameTextField.text password:_passwordTextField.text];
[self.navigationController popToRootViewControllerAnimated:YES];
(2)在A控制器界面;
// 遵守B协议
@interface AViewController ()<BViewControllerDelegate>
@property (nonatomic, strong) UILabel *usernameLabel;
@property (nonatomic, strong) UILabel *passwordLabel;
@end
// 控制器跳转,设置代理
BViewController *vc = [[BViewController alloc] init];
// 设置B的代理
vc.delegate = self;
[self.navigationController pushViewController:vc animated:YES];
// 实现代理方法
#pragma mark - ——————————— BViewControllerDelegate ———————————
- (void)sendUsername:(NSString *)username password:(NSString *)password
{
self.usernameLabel.text = username;
self.passwordLabel.text = password;
}
4.block传值
代理能实现的,block基本上都可以实现,并且比代理使用起来简单;
关键字copy声明,B页面跳转回A页面;
(1).在B控制器中
// 别名表示
typedef void(^ReturnIDCardInfoBlock)(NSString *name, NSString *sex);
// .h文件中声明为属性,注意copy修饰
@property (nonatomic, copy) ReturnIDCardInfoBlock returnIDCardInfoBlock;
// .m实现文件中存值
self.returnIDCardInfoBlock(self.nameTextField.text, self.sexTextField.text);
(2).在A控制器中
BViewController *vc = [[BViewController alloc] init];
vc.returnIDCardInfoBlock = ^(NSString *name, NSString *sex) {
_name = name;
_sex= sex;
};
[self.navigationController pushViewController:vc animated:YES];
(1)"强弱引用"
修饰强引用的关键字'__strong',简单理解为:强制持有对象,对象的引用计数+1;
修饰弱引用关键字'__weak',简单理解为:不持有对象,对象的引用计数不变;
如果【block内部】使用了【外部声明的强引用】访问【对象A】,那么【block内部】会自动产生于一个【强引用】指向【对象A】;
如果【block内部】使用了【外部声明的弱引用】访问【对象A】,那么【block内部】会自动产生于一个【弱引用】指向【对象A】;
(2)"循环引用"
简单理解为:A对象持有B对象的同时,B对象又持有A,导致A、B都无法释放;
5.通知传值
跨界面传值
(1).在需要传值的界面
NSDictionary *dic = @{@"username":self.usernameTextField.text, @"password":self.passwordTextField.text};
// 发送通知(传值)
[[NSNotificationCenter defaultCenter] postNotificationName:@"userLoginNotification" object:nil userInfo:dic];
(2).接受值的界面
// 注册通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userLogin:) name:@"userLoginNotification" object:nil];
// 实现通知的方法(接收值)
- (void)userLogin:(NSNotification *)notification
{
NSLog(@"接收到通知");
NSLog(@"%@",notification.userInfo[@"username"]);
NSLog(@"%@",notification.userInfo[@"password"]);
}
// 移除通知
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"userLoginNotification" object:nil];
6.NSUserdefault
既可以正向传值,也可以反向传值,多用于跨界面传值;
是写入沙盒,以文件的形式进行传值;
// 存值
[[NSUserDefaults standardUserDefaults] setValue:self.usernameTextField.text forKey:@"username"];
[[NSUserDefaults standardUserDefaults] synchronize] ;
// 取值
NSString *username = [[NSUserDefaults standardUserDefaults] objectForKey:@"username"];
注意:键值对key的唯一性;