iOS学习之六种传值方式
iOS页面传值方式
应用于:
- 两个互动的界面:1)页面一跳转到页面二,页面一的textField的值传给页面二的label。2)A页面跳转到B页面,B页面再跳转回A页面(注册页面跟登录页面)
- 两个不互动的两个界面:数据持久层跟表示层的数据交互。
几种传值方式:
- 属性传值
- 委托delegate方式
- 通知notification方式
- block方式
- 单例模式方式
- UserDefault或者文件方式
1.属性传值(顺传):
- 需要定义一个公开的属性
- 需要一个你需要传值的对象
- 进行属性赋值
实现:A、B两个界面,通过按钮将A界面textField的值传给页面B的label。
A:ViewController B:DetailViewController
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UITextField *textField;
@end
@implementation ViewController
-(void)buttonAction:(UIButton *)button
{
DetailViewController *detailViewController =
[[DetailViewController alloc]init];//用下一个视图的属性接受想要传过去的值,属性传值
detailViewController.firstValue = self.txtFiled.text;
[self.navigationController pushViewController:second animated:YES];
}
DetailViewController界面
#import "DetailViewController.h"
@interface DetailViewController ()
@property (nonatomic, weak) NSString firstValue;//接收textField传过来的值。
@end
2.代理传值(顺传倒传都可以)
delegate只能是一对一之间的。他只能是navigation的栈里面的相邻控制器传值, 不能跨控制器传值。比如:a到b,b到c.,而不能从c传到a.
- 拟定⼀份协议(命名一般是XXXDelegate),协议里面的⽅法的参数取决于你要传递的内容
- 设置代理人属性(再次强调,使用assign防⽌循环引用)
- 在需要调⽤的地⽅调⽤,这⼀步比较抽象,⽐如上面所讲例⼦子,我们是需要在button点击的时候
- 传值并且取消界面,所以我们的delegate就在这个⽅面的进⾏调用
- 让相应的对象成为代理人,⼀般都是在创建的时候指定一个代理⼈
- 遵守协议,并且实现相应的方法,然后在方法中进行逻辑处理
实现:A页面push到B页面,如果 B页面的信息想回传(回调)到A页面,用代理传值,其中B定义协议和声明代理,A确认并实现代理,A作为B的代理
A页面:RootViewControllers B页面:DetailViewControllers
ViewControllers.h文件
#import <UIKit/Uikit.h>
@class DetailViewController;
@protocol PassingValueDelegate<NSObject>//拟定协议
@optional
-(void)passValues:(NSString *)values;//定义协议方法(values你想要传递的内容)
@end
@interface ViewControllers: UIViewController
@property (nonatomic, weak)id< PassingValueDelegate > delegate; (valueDelegate)//设置代理属性,通过其传值(为防止循环引用,此处采用了weak或者assign)
点击按钮事件函数(调用代理)
-(void)trendBtnClick{
//create the view
DetailViewController * detailViewController = [[DetailViewController alloc] initWithNibName:@" DetailViewController " bundle:nil]; //传值并且取消界面
self.delegate (自己命名的valueDelegate )= detailViewController; //设置代理 ,让相应的对象成为代理人
[self.trendDelegate passValues:@""];
//页面跳转
}
DetailViewController.h 文件
引用ViewController的头文件,并添加代理协议如下
#import "ViewController.h"
@interface TrendViewController : UIViewController<PassTrendValueDelegate>{
}
@end
实现代理函数:
#pragma mark 实现传值协议方法
-(void)passValues:(NSString *)values{
NSLog(@"values=%@",values);
}
最重要也是最容易忽略的,就是一定要设置delegate的指向
3.通知传值(顺传倒传都可以)第三个页面的值传给第一个页面
谁要监听值的变化,谁就注册通知 ,特别要注意,通知的接受者必须存在这一先决条件不用通知的时候,记得移除。
- 在第三个界面中, 建⽴一个通知中心, 通过通知中心, 发送通知(发送通知的过程就是传值的过程,将要传输的值作为object的值传给第一个界面
- 在第⼀个界面建⽴一个通知中心, 通过通知中⼼,注册一个监听事件
- 在第一个界⾯中,设置接收到通知的事件。
- 在第⼀个界⾯面中的dealloc中, 将通知中心remove掉
任何对象对可以发送通知到中心,同时任何对象可以监听中心的通知。
发送通知的代码如下:
[[NSNotificationCenter defaultCenter] postNotificationName:@”myNotificationName” object:broadcasterObject];
注册接收通知的代码如下:
[[NSNotificationCenter defaultCenter] addObserver:listenerObject selector:@selector(receivingMethodOnListener:) name:@”myNotificationName” object:nil];
实现:将B界面的值传给A界面,所以B界面发送通知到通知中心,A界面注册成为监听者,监听B值的变化,接受从通知中心回传的B的值。如果c页面也想接受B的值,也同样注册成为监听者就行。(所以可以实现多对多)
A界面:RootViewController B界面:SecondViewController
在B界面建立通知中心,将要传的值nameTextField.text通过通知中心发送
//SecondViewController.m
-(IBAction)notificationMethod:(id)sender {
[[NSNotificationCenter defaultCenter] postNotificationName:@'ChangeNameNotification' object:self userInfo:@{@'name':self.nameTextField.text}];
[self dismissViewControllerAnimated:YES completion:nil];
}
在A页面的控制器中,注册通知:
//RootViewController.m
- (void)viewDidLoad.{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ChangeNameNotification:) name:@'ChangeNameNotification' object:nil];
}
调用,显示
//RootViewController.m
-(void)ChangeNameNotification:(NSNotification*)notification{
NSDictionary *nameDictionary = [notification userInfo];
self.nameLabel.text = [nameDictionary objectForKey:@'name'];
.}
当我们不使用时,要记得删掉通知:
//RootViewController.m
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
4. block传值(顺传倒传都可以)block同样用于回调
- 为block取别名。并且在参数列表中将需要传递的参数写形参
- 设置block属性(注意使用copy)
- 设置一个方法持有当前block
- 在合适的地方进行调用类似代理
- 在创建该对象的地方进行block方面的调用
//block语法
//返回值类型 (^block参数名) (参数类型 参数名) = ^返回值类型 (参数类型 参数名)
实现:将B界面的textField.text传给A界面的Label
A页面:RootViewControllers B页面:DetailViewControllers
DetailViewController文件
#import <UIKit/Uikit.h>
typedef void (^DetailBlock)(NSString *);//block取别名。并且在参数列表中将需要传递的参数写形参
@interface DetailViewController : UIViewController
@property (nonatomic, copy) PassingValueBlock passingvalue;//设置block属性(注意使用copy)
@property (weak, nonatomic) UITextField *inputTF;
@end
- (IBAction)BtnAction:(id)sender {
//判断block是否为空
if (self.NextViewControllerBlock) {
self.NextViewControllerBlock(self.inputTF.text);
}
[self.navigationController popViewControllerAnimated:YES];
}//点击按钮到A界面
RootViewController.m
@property (strong, nonatomic) UILabel *textLabel;
-(void)handleButton: (NSString*)sender{
DetailViewController *detailViewController = [[DetailViewController alloc]init];
detailViewController.passingValue=^( NSString* str){
self. textLabel.text= str;}
[self.navigationController pushViewController:detailViewController animated:YES];
}
5. 单例传值(顺传倒传都可以)
单例的好处就在于只是创建了一次,其余任何时候访问到的对象都是同一个,所以很多时候用到用户的一些信息都是保存在单例中的,这样就不需要多次传值了,只需要再次创建单例就可以了
AppStatus.h 创建一个单例类 AppStatus
#import <Foundation/Foundation.h>
@interface AppStatus : NSObject
{
NSString *_contextStr;
}
@property(nonatomic,retain)NSString *contextStr;
+(AppStatus *)shareInstance;
@end
AppStatus.m
#import "AppStatus.h"
@implementation AppStatus
@synthesize contextStr = _contextStr;
static AppStatus *_instance = nil;
+(AppStatus *)shareInstance
{
if (_instance == nil)
{
_instance = [[super alloc]init];
}
return _instance;
}
-(id)init
{
if (self = [super init])
{
}
return self;
}
@end
RootViewController.h
#import "RootViewController.h"
#import "DetailViewController.h"
#import "AppStatus.h"
@interface RootViewController ()
@end
@implementation RootViewController
-(void)pushAction:(id)sender
{
tf = (UITextField *)[self.view viewWithTag:];
//单例传值 将要传递的信息存入单例中(共享中)
// [[AppStatus shareInstance]setContextStr:tf.text]; 跟下面这种写法是等价的
[AppStatus shareInstance].contextStr = tf.text;
//导航push到下一个页面
DetailViewController *detailViewController = [[DetailViewController alloc]init];
//导航push到下一个页面
[self.navigationController pushViewController:detailViewController animated:YES];
}
@end
DetailViewController.h
#import <UIKit/UIKit.h>
@protocol ChangeDelegate;//通知编译器有此代理
@interface DetailViewController : UIViewController
{
UITextField *textField;
}
@end
#import "DetailViewController.h"
#import "AppStatus.h"
@interface DetailViewController ()
@end
@implementation DetailViewController
@synthesize naviTitle = _naviTitle;
-(void)loadView
{
self.view = [[[UIView alloc]initWithFrame:CGRectMake(, , , )]autorelease];
//单例
self.title = [AppStatus shareInstance].contextStr;
textField = [[UITextField alloc]initWithFrame:CGRectMake(, , , )];
textField.borderStyle = UITextBorderStyleLine;
[self.view addSubview:textField];
UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDonetarget:self action:@selector(doneAction:)];
self.navigationItem.rightBarButtonItem = doneItem;
[doneItem release];
}
//这个方法是执行多遍的 相当于刷新view
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
tf = (UITextField *)[self.view viewWithTag:];
tf.text = [AppStatus shareInstance].contextStr;
}
//pop回前一个页面
-(void)doneAction:(id)sender
{
//单例传值
[AppStatus shareInstance].contextStr = textField.text;
[self.navigationController popToRootViewControllerAnimated:YES];
}
6.NSUserDefault传值(顺传倒传都行)
[[NSUSerDefault standardUserDefaults]setObject:要传的值 forKey:对这个值得标记键];//设置值
[[NSUserDefault standardUserDefaults]ObjectForKey:根据你的标记键];//获取值
iOS学习之六种传值方式的更多相关文章
- iOS学习——页面的传值方式
一.简述 在iOS开发过程中,页面跳转时在页面之间进行数据传递是很常见的事情,我们称这个过程为页面传值.页面跳转过程中,从主页面跳转到子页面的数据传递称之为正向传值:反之,从子页面返回主页面时的数据传 ...
- ios学习-delegate、传值、跳转页面
ios学习-delegate.传值.跳转页面 1.打开xcode,然后选择ios--Application--Empty Application一个空项目. 项目目录: 2.输入项目名称以及选 ...
- ios常见的页面传值方式
iOS页面间的传值细分有很多种,基本的传值方式有三种:委托Delegate传值.通知NSNotification传值.Block传值,其他在项目中可能会遇到的还有:UserDefault或文件方式传值 ...
- iOS的四种传值方式
传值有四种方法 : 1. 属性传值 2. 单例传值 3. 代理传值 4. block传值 一.属性传值 (前-->后) 1. 后面的界面定义一个属性 存放前一个界面传过来的值 ...
- 【转】ios -- ViewController跳转+传值(方式一)
方式一:通过定义一个实体类传值 (从ViewController1 跳转至 ViewController2) 1.定义实体类NotificationEntity .h声明文件 #import < ...
- iOS 学习 - 1.代理传值
代理的目的是改变或传递控制链.允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针.可以减少框架复杂度. 另外一点,代理可以理解为java中的回调监听机制的一种类似 优点:1.避免子类化带 ...
- iOS学习之页面之间传值的方式总结
传值三种场景: 1.属性传值(从前往后传) 需求:第二个界面标签显示第一个界面输入框文字. 第一步, 在前一个界面定义属性. (语义属性声明为copy); 第二步, 在进入下一个界面之前,给属性传入数 ...
- iOS页面传值方式
普遍传值方式如下: 1.委托delegate方式: 2.通知notification方式: 3.block方式: 4.UserDefault或者文件方式: 5.单例模式方式: 6.通过设置属性,实现页 ...
- iOS多视图传值方式之通知传值(NSNotification;NSNotificationCenter)
iOS传值方式之5:通知传值 第一需要发布的消息,再创建NSNotification通知对象,然后通过NSNotificationCenter通知中心发布消息(NSNotificationCenter ...
随机推荐
- 車(rook)
[题目分析] JustPenz:我们假设n>m(不大于就交换),那最多能摆m个,所以会有(n-m)个空白,我们把这些空白插入到n中,答案就是C(n,n-m)=C(n,m);数据范围比较大,我们就 ...
- winform的常用公共控件和常用属性
我们在学位winform的控件和属性的时候要学会赋值取值还有改值 公共控件: 1,Button(按钮): Enabled :是否可用 Visible:是否可见 2,CheckBox(多选项) Chec ...
- (转)Could not create the view: An unexpected exception was thrown. 电脑突然断电,myeclipse非正常关闭,出现错误
问题:电脑突然断电,myeclipse非正常关闭,“Package Explorer”非正常显示,出现错误“Could not create the view: An unexpected excep ...
- WIN10图标显示异常
1.打开控制面板,右上边查看方式选择边小图标显示 2.打开显示里面的自定义缩放级别 3.设置级别为125% 然后点击 应用 4.注销或者重启,然后将异常的快捷方式点击打开,就会恢复正常,至少我的是回 ...
- SQL循环索引
),dates datetime) insert @tbl(order_id,dates) select 'A','2014-1-1' union select 'A','2014-2-1' unio ...
- java程序调用存储过程
java程序调用存储过程 PL/SQL子程序,很多情况下是给应用程序来调用的,所有我们要掌握使用其他编程语言来调用我们写好的存储过程.下面我们介绍下使用java调用Oracle的存储过程. ...
- hdu3065病毒侵袭持续中
链接 上一篇的姊妹篇 没啥好说的 套模板 #include <iostream> #include<cstdio> #include<cstring> #inclu ...
- Python简单时间日期处理
import datetime #日期初始化: d1 = datetime.datetime(2005, 2, 16) d2 = datetime.datetime(2004, 12, 31) #日期 ...
- Spring + Mybatis 使用 PageHelper 插件分页
原文:http://www.cnblogs.com/yucongblog/p/5330886.html 先增加maven依赖: <dependency> <groupId>co ...
- 【转载】CSS规范
原文地址:http://www.cnblogs.com/whitewolf/p/4491707.html 目录 HTML 语法 HTML5 doctype 语言属性(Language attribut ...