ios常用传值小结

来源:互联网 发布:没有网站怎么做淘宝客 编辑:程序博客网 时间:2024/05/22 14:34

iOS常用传值小结

***************************

##最简单的用第二个界面的label来显示第一个界面的textField中的文本

(一)属性传值—-前向后传值

1.我们首先要在RootViewController的基础上创建一个DetailViewController,然后我们要记住传值过程中用到什么类型就定义什么属性,因此我们需要在DetailViewController页面声明一个textString属性,来接收传过来的字符串,

/*
* 声明一个textString属性,用于接收传过来的字符串
* —- 属性传值
*/
@property (nonatomic, copy) NSString *textString;

2.接下来我们来创建显示的label

/*
* 创建label用于显示传过来的字符串
*/
-(void)createUIFrame{

  UILabel *xianshiLab = [[UILabel alloc] initWithFrame:CGRectMake(20, 300, [UIScreen mainScreen].bounds.size.width - 40, 100)];  xianshiLab.backgroundColor = [UIColor greenColor];xianshiLab.font = [UIFont systemFontOfSize:13.0f];xianshiLab.numberOfLines = 0;/* *  使用属性传递得到的文本 */xianshiLab.text = self.textString;[self.view addSubview:xianshiLab];

}

3.我们需要在RootViewController中引入DetailViewController同时还要声明一个属性来输入字符串(可选择)textField,

/*
* 声明一个textfield属性来输入字符串
*/

@property (nonatomic, copy) UITextField *textField;

创建button并给textField相关属性赋值

-(void)createUIFrame{

_textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 100, [UIScreen mainScreen].bounds.size.width-40, 40)];_textField.borderStyle = UITextBorderStyleRoundedRect;_textField.layer.borderColor = [UIColor blackColor].CGColor;_textField.layer.borderWidth = 1.0f;_textField.placeholder = @"请输入字符串";[self.view addSubview:_textField];/* *  添加手势,取消键盘第一响应 */UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap)];[self.view addGestureRecognizer:tap];/* *  创建button */UIButton *pushBtn = [UIButton buttonWithType:UIButtonTypeCustom];pushBtn.frame = CGRectMake(0, 0, 80, 40);[pushBtn setTitle:@"跳转传值" forState:UIControlStateNormal];pushBtn.titleLabel.font = [UIFont systemFontOfSize:16.0f];pushBtn.center = self.view.center;[pushBtn addTarget:self action:@selector(handlePush:) forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:pushBtn];

}

4.通过button的点击事件完成整个属性传值
pragma mark —– 点击事件—

-(void)handlePush:(UIButton *)sender{

DetailViewController *detailVC = [[DetailViewController alloc] init];/* *   属性传值 */detailVC.textString = self.textField.text;    [self.navigationController pushViewController:detailVC animated:YES];

}
-(void)handleTap{

[self.view endEditing:YES];

}

(二)代理传值

在项目中,我们经常遇到,当RootViewController页面Push到DetailViewController,而我们DetailViewController页面的一些信息想要回传(回调)到RootViewController,这时候就用到了回调
*需要注意DetailViewController页面定义协议和声明代理,RootViewController页面确认并实现代理。RootViewController作为DetailViewController的代理
1.首先我们在DetailViewController的.h文件中创建协议方法

/*
* 代理传值
*/
@class DetailViewController;
@protocol passingValueDelegate
@optional

-(void)viewController:(DetailViewController *)viewcontroller didPassingValueWithInfo:(id)info;

@end

/*
* 通过代理对象传值
*/
@property (nonatomic, assign) iddelegate;

2.在DetailViewController的.m中我们判定代理对象存在时,为其绑定相应的方法

/*
* 我们判定代理对象存在时,为其绑定相应方法
*/

-(void)viewWillDisappear:(BOOL)animated{

[super viewWillDisappear:animated];/* *  视图将要消失时,通过代理传值 *  首次判定代理是否存在,并且代理能够响应代理方法时,才执行代理方法 */if (self.delegate && [self.delegate respondsToSelector:@selector(viewController:didPassingValueWithInfo:)]) {    /*     *  传递当前视图的背景颜色     */    [self.delegate viewController:self didPassingValueWithInfo:self.view.backgroundColor];}

}

3.在RootViewController的.m文件中我们指定代理并让其执行代理的方法

pragma mark —– 点击事件—

-(void)handlePush:(UIButton *)sender{

DetailViewController *detailVC = [[DetailViewController alloc] init];    /* *  代理传值  为detailVC指定代理对象 * /detailVC.delegate = self;   [self.navigationController pushViewController:detailVC animated:YES];

}
-(void)viewController:(DetailViewController *)viewcontroller didPassingValueWithInfo:(id)info{

/* *  把第二个视图的颜色传给第一个视图 */self.view.backgroundColor = info;

}
到这里就已经完成了整个过程

(三)回调传值

在iOS中,关于block的用法非常多,传值只是其中一个很小的用法,它在页面消失(或跳转)的瞬间完成传值。
1.我们要使用block首先要先在第二个视图控制器的.h文件中定义Block属性

typedef void(^returnBlock)(NSString *showText);
@interface SecondViewController : ViewController
//声明block 属性
@property (nonatomic,strong)returnBlock returnTextBlock;
//声明 调用方法
- (void) returnText: (returnBlock)block;

在这里我们第一行给要声明的Block重新定义了一个名字:ReturnTextBlock 随后均使用这个名字
第三行定义了一个Block属性
第四行是在第一个界面传进来一个Block语句块的函数(可不用,但加上会减少代码量)
2.接下来实现第二个视图控制器的方法就可以了

-(void) returnText:(returnBlock)block{

self.returnTextBlock = block;  

}
-(void)viewDidDisappear:(BOOL)animated
{

//即将消失的时候if (self.returnTextBlock !=nil) {    self.returnTextBlock(self.textField.text);}NSLog(@"======%@=======",self.returnTextBlock);

}

这里面第一个方法就是定义的那个方法,把传进来的Block语句块保存到本类的实例化变量returnTextBlock(.h重定义的属性中),然后寻找一个时机调用,这就是第二个方法,在视图即将消失时调用。
3.在第一个视图控制器中获得第二个视图控制器,并且用第二个来调用定义的属性

-(void)viewDidLoad {

[super viewDidLoad];SecondViewController *secondVc = [[SecondViewController alloc] init];[secondVc returnText:^(NSString *showText) {    NSLog(@"---------%@------------",showText);    self.secTextField.text = showText;}];self.secVc = secondVc;self.secVc.delegate = self;

}

这样我们就可以完成整个的回调功能,从而达到了传值的目的。

链接一篇描述block回调挺有意思的文章:http://blog.csdn.net/mobanchengshuang/article/details/11751671

(四) 通知传值

*注意:谁要监听值的变化,谁就注册通知,通知的接收者必须存在
1.首先我们要在第二个控制器中进行相应操作

/*
* 注册通知
*/

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tongzhi:) name:@"tongzhi" object:nil];

/*
* 接收通知传值
*/

-(void)tongzhi:(NSNotification *)text{

NSLog(@"%@",text.userInfo[@"textOne"]);NSLog(@"--------接收到通知-------");/* *  移除通知 */[[NSNotificationCenter defaultCenter] removeObserver:self name:@"tongzhi" object:nil];

}

2.在第一个控制器中执行点击监听方法

pragma mark —– 点击事件—

-(void)handlePush:(UIButton *)sender{

/* *  通知传值 *  输入要发送的信息,同时将label的值通过button方法调用过去 * *  添加字典,将label的值通过key值设置传递 */NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:self.textFieldOne.text,@"textOne",self.textFieldTwo.text,@"textTwo", nil];/* *  创建通知 *  通过通知中心发送通知 */NSNotification *notifiction = [NSNotification notificationWithName:@"tongzhi" object:nil userInfo:dict];[[NSNotificationCenter defaultCenter] postNotification:notifiction];[self.navigationController pushViewController:detailVC animated:YES];

}


本地化存储,较为简单,将需要的信息存起来,用的时候取出来,最后释放即可:

        NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];        [defaults setObject:dict forKey:@"login"];        [defaults synchronize];
释放:
        NSUserDefaults * defaults =[NSUserDefaults standardUserDefaults];        [defaults removeObjectForKey:@"login"];        [defaults synchronize];  

*另外还存在几种传值方式,但是我使用较少,几乎不用,所以无法进行总结***

(1)SharedApplication定义一个变量来传递(单例)
(2)通过文件 或者NSUserdefault来传递

//通过文件或者UserDefault方式存值(感觉不太适合此类传值,如果要用文件或者UserDefault方式存值的话,可以考虑此方式)

-(IBAction)userDefaultMethod:(id)sender {

if ([self notEmpty]) {    [[NSUserDefaults standardUserDefaults] setObject:self.nameTextField.text forKey:@"myNameText"];    [self dismissViewControllerAnimated:YES completion:nil];}else{    [self showAlert];}

}

在A控制器显示

-(void)viewDidAppear:(BOOL)animated{

[super viewDidAppear:animated];//如果想测试通过UserDefault方式传值或者通过单例方式传值,取消以下注释即可

/*

if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"myNameText"] length] != 0) {    self.nameLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"myNameText"];    [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"myNameText"];}DataSource *dataSource = [DataSource sharedDataSource];if ([dataSource.myName length] != 0) {    self.nameLabel.text = dataSource.myName;    dataSource.myName = @"";}

*/
}

(3)通过单例的class来传递
在B控制器

//通过单例方式传值(感觉不太适合此类传值,如果要用单例方式传值的话,可以考虑此方式)

-(IBAction)singletonMethod:(id)sender {

if ([self notEmpty]) {    DataSource *dataSource = [DataSource sharedDataSource];    dataSource.myName = self.nameTextField.text;    [self dismissViewControllerAnimated:YES completion:nil];}else{    [self showAlert];}

}

这里面用到了单例模式,编写了DataSource类。存放数据
#import
#import “DataSource.h”

@implementation DataSource

+(DataSource *)sharedDataSource{

static DataSource *dataSource = nil;static dispatch_once_t once;dispatch_once(&once, ^{    dataSource = [DataSource new];});return dataSource;

}
@end

0 0
原创粉丝点击