iOS传值的几种方式
iOS传值的几种方式
介绍
在这里我会给大家讲解iOS中比较常见的几种传值方式,如果你能熟练掌握这几种方式,那么你对传值的理解将会更上一层楼。
环境:XCode6.3
模拟器:iPhone 6
首先我们来创建一个SingleViewApplication工程
自定义初始化传值
首先我们进入到ViewController.m文件,这是系统默认的rootViewController,所以一旦工程执行,系统就会执行ViewController中的viewDidLoad方法。在此我们首先定义几个方法,并且遵守UITextFieldDelegate这个协议
//
// ViewController.m
// iOS传值
//
// Created by archerzz on 15/5/18.
// Copyright (c) 2015年 archerzz. All rights reserved.
//
#import "ViewController.h"
@interface ViewController () <UITextFieldDelegate>
@property (nonatomic, strong) UITextField *textField;
- (void)initializeUserInterface;
- (void)handleButtonEvent:(UIButton *)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initializeUserInterface];
}
- (void)initializeUserInterface {
_textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 100, 375, 30)];
// 设置自动纠正
_textField.autocorrectionType = UITextAutocorrectionTypeNo;
// 设置自动大小写
_textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
// 设置边框
_textField.borderStyle = UITextBorderStyleRoundedRect;
// 设置代理
_textField.delegate = self;
[self.view addSubview:_textField];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
// 设置标题
[button setTitle:@"登录" forState:UIControlStateNormal];
// 设置大小
[button setBounds:CGRectMake(0, 0, 100, 30)];
// 设置中心点
[button setCenter:CGPointMake(180, 400)];
[self.view addSubview:button];
// 添加点击事件
[button addTarget:self action:@selector(handleButtonEvent:) forControlEvents:UIControlEventTouchUpInside];
}
#pragma mark - ButtonEvent 方法
- (void)handleButtonEvent:(UIButton *)sender {
}
#pragma mark - UITextFieldDelegate 方法
// 是否能够return
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
// 取消第一响应者,目的取消键盘
[textField resignFirstResponder];
return YES;
}
@end
而现在我们要做的事情就是将文本框中输入的文本传入到下一个界面。所以首先我们来创建一个新的控制器(DetailViewController),并且创建了一个自定义初始化方法,目的:传值
#import <UIKit/UIKit.h>
@interface DetailViewController : UIViewController
- (instancetype)initWithText:(NSString *)text;
@end
接下来我们看.m文件
#import "DetailViewController.h"
@interface DetailViewController ()
@property (nonatomic, strong) NSString *text;
@end
@implementation DetailViewController
- (instancetype)initWithText:(NSString *)text {
if (self = [super init]) {
self.text = text;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
// 显示到label上了
NSLog(@"%@", self.text);
}
@end
现在只需要最后一步,就是点击页面的登录,然后跳转页面.回到ViewController中的button点击事件
#pragma mark - ButtonEvent 方法
- (void)handleButtonEvent:(UIButton *)sender {
// 注意首先导入头文件
// 利用我们刚才所写的自定义初始化方法,进行传值
DetailViewController *detailVC = [[DetailViewController alloc] initWithText:self.textField.text];
// 推送
[self presentViewController:detailVC animated:YES completion:nil];
}
最后你可以看到控制台中的打印文本就是你在前一个页面所输入的文本
总结:
自定义初始化方法在UI中,一般都是用在一个界面去推送另一个界面的时候,总之你要想到既然要用自定义初始化方法,至少能够要在当前方法中去创建该对象。所以这种方式不适合回调。
步骤:
- 自定义初始化方法,将需要传递的内容作为参数,如果需要传递多个,则设置多个参数.
- 在合适的地方进行调用自定义初始化方法。
属性传值
属性传值,可以做自定义初始化方法的事情,也就说明上面我所讲的可以用属性传值来取代。只需要将
@property (nonatomic, strong) NSString *text;
这个属性写到.h文件,这样外界就能访问了,同样在button点击事件中,如下代码就可以用到属性传值了
#pragma mark - ButtonEvent 方法
- (void)handleButtonEvent:(UIButton *)sender {
// 注意首先导入头文件
// 利用我们刚才所写的自定义初始化方法,进行传值
// DetailViewController *detailVC = [[DetailViewController alloc] initWithText:self.textField.text];
// 推送
// 属性传值
DetailViewController *detailVC = [[DetailViewController alloc] init];
detailVC.text = _textField.text;
[self presentViewController:detailVC animated:YES completion:nil];
}
当然,属性传值还可以用到其他地方,总之你能够获取到当前对象属性,那么你就可以利用属性传值
总结:
- 需要定义公开属性
- 需要一个你需要传值的对象
- 进行属性赋值
代理传值
我们知道在iOS中,系统采用了大量的代理这种方式进行回调传值.那么在这里我来讲解怎么自定义代理传值
在这里我们来模拟如下效果,当用户点击登录之后,我们跳转到detaiVC这个界面,在detailVC中我们能够修改当前用户名,并且让viewController中的输入的文本变成detailVC中输入的文本。这种情况,两个对象都已经存在,并且是第2个界面往第1个界面回调。
首先我们在DetailVC中加入1个方法,并且在viewDidLoad中进行调用
- (void)initializeUserInterface {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 200, 375, 30)];
label.text = [@"当前用户名:" stringByAppendingString:_text];
label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:label];
_textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 300, 375, 30)];
_textField.autocorrectionType = UITextAutocorrectionTypeNo;
_textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
_textField.placeholder = @"请修改用户名";
_textField.textAlignment = NSTextAlignmentCenter;
_textField.borderStyle = UITextBorderStyleRoundedRect;
[self.view addSubview:_textField];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
// 设置标题
[button setTitle:@"注销并修改用户名" forState:UIControlStateNormal];
// 设置大小
[button setBounds:CGRectMake(0, 0, 200, 30)];
// 设置中心点
[button setCenter:CGPointMake(180, 400)];
[self.view addSubview:button];
// 添加点击事件
[button addTarget:self action:@selector(handleButtonEvent:) forControlEvents:UIControlEventTouchUpInside];
}
然后添加点击事件
- (void)handleButtonEvent:(UIButton *)sender {
}
接下来就是开始自定义协议
#import <UIKit/UIKit.h>
// 第一步创建协议
@protocol DetailViewControllDelegate <NSObject>
- (void)buttonDidPressed:(NSString *)text;
@end
@interface DetailViewController : UIViewController
@property (nonatomic, strong) NSString *text;
// 第二步设置代理人属性(注意assign)
@property (nonatomic, assign) id<DetailViewControllDelegate> delegate;
- (instancetype)initWithText:(NSString *)text;
@end
其次.m文件
- (void)handleButtonEvent:(UIButton *)sender {
// 第三步在需要的地方调用
// 在当前程序就是希望在这里进行调用
if (self.delegate && [self.delegate conformsToProtocol:@protocol(DetailViewControllDelegate)]) {
[self.delegate buttonDidPressed:_textField.text];
[self dismissViewControllerAnimated:YES completion:nil];
}
}
然后进入ViewController.m文件,注意下面多了一行代码 第4步
#pragma mark - ButtonEvent 方法
- (void)handleButtonEvent:(UIButton *)sender {
// 注意首先导入头文件
// 利用我们刚才所写的自定义初始化方法,进行传值
// DetailViewController *detailVC = [[DetailViewController alloc] initWithText:self.textField.text];
// 推送
// 属性传值
DetailViewController *detailVC = [[DetailViewController alloc] init];
detailVC.text = _textField.text;
// 第4步设置代理,并遵守协议
detailVC.delegate = self;
[self presentViewController:detailVC animated:YES completion:nil];
}
最后
#pragma mark - DetailViewControllDelegate 方法
// 第5步实现协议方法
- (void)buttonDidPressed:(NSString *)text {
_textField.text = text;
}
总结:
- 拟定一份协议(命名一般是XXXDelegate),协议里面的方法的参数取决于你要传递的内容
- 设置代理人属性(再次强调,使用assign防止循环引用)
- 在需要调用的地方调用,这一步比较抽象,比如上面所讲例子,我们是需要在button点击的时候传值并且取消界面,所以我们的delegate就在这个方面的进行调用
- 让相应的对象成为代理人,一般都是在创建的时候指定一个代理人
- 遵守协议,并且实现相应的方法,然后在方法中进行逻辑处理
block传值
block传值其实和上面步骤都差不多,但是多了一个对于block的理解,block也是在传值中用于回调,在这里我来将上面的代码用block写一次
同样首先进行DetaiViewController.h文件
// 第一步
typedef void(^CallBack)(NSString *text);
// 第二步
@property (nonatomic, copy) CallBack callBack;
// block第三步
- (void)buttonPressWithCallBack:(CallBack)callback;
接着进入.m文件
// block 第4步
- (void)buttonPressWithCallBack:(CallBack)callback {
self.callBack = callback;
}
- (void)handleButtonEvent:(UIButton *)sender {
// block第五步
if (self.callBack) {
self.callBack(_textField.text);
[self dismissViewControllerAnimated:YES completion:nil];
}
}
最后进入ViewController.m文件
#pragma mark - ButtonEvent 方法
- (void)handleButtonEvent:(UIButton *)sender {
// 注意首先导入头文件
// 利用我们刚才所写的自定义初始化方法,进行传值
// DetailViewController *detailVC = [[DetailViewController alloc] initWithText:self.textField.text];
// 推送
// 属性传值
DetailViewController *detailVC = [[DetailViewController alloc] init];
detailVC.text = _textField.text;
// block最后一步 调用block方法
[detailVC buttonPressWithCallBack:^(NSString *text) {
NSLog(@"%@", text);
}];
[self presentViewController:detailVC animated:YES completion:nil];
}
总结:block同样用于回调
- 为block取别名,并且在参数列表中将需要传递的参数写成形参
- 设置block属性(注意使用copy)
- 设置一个方法持有当前block
- 在合适的地方进行调用类似于代理
- 在创建该对象的地方进行block方面的调用
单例传值
相信大家现在对单例有一定的认识,如果不知道单例是什么,那么就先搜索下单例的使用方式,单例的好处就在于只要创建了一次,其余任何时候访问到的对象都是同一个,所以很多时候用户的一些信息都是存储到单例中,这样就不需要多次进行传值了,只需要再次创建单例就可以了
首先我们来创建一个单例,继承于NSObject
#import <Foundation/Foundation.h>
@interface UserInfo : NSObject
@property (nonatomic, strong) NSString *username;
@property (nonatomic, strong) NSString *password;
+ (instancetype)sharedUserInfo;
@end
#import "UserInfo.h"
@implementation UserInfo
+ (instancetype)sharedUserInfo
{
static id instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[[self class] alloc] init];
});
return instance;
}
@end
make by