使用模型传递数据
#import <Foundation/Foundation.h>
@interface UserModel : NSObject
@property(nonatomic,retain) NSString *userName;
@property(nonatomic,retain) NSString *gendar;
@property(assign) int age;
@end
@interface ViewController ()
@property (strong,nonatomic) UserModel *userModel;
@end
- (void)viewDidLoad 的时候就要初始化 UserModel
- (void)viewDidLoad
{
[super viewDidLoad];
_userModel = [[UserModel alloc] init];
}
这时,你的界面一中,user对象就有3个属性, userName; gender; age。此时 把你需要传递的数据赋给它们,在此 仅以userName为例。
_userModel.userName = self.userNameTextFiled.text;
@property (strong,nonatomic) UserModel *userModel;
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:[NSBundle mainBundle]];
//设置SecondViewController中的值
secondView.userModel = _userModel;
//跳转界面
[self presentModalViewController:secondView animated:YES];
此时, 界面二的 userModel则有值了,值即为界面一中的self.userNameTextFiled.text。 然后在界面二中显示出来:
self.userNameTextField.text = self.userModel.userName;
self.userEntity.userName = self.userNameTextField.text;
[self dismissModalViewControllerAnimated:YES];
把这个值继续赋给自己的模型即可。
-(void)viewWillAppear:(BOOL)animated{
[super viewDidAppear:animated];
self.userNameTextFiled.text = self.userModel.userName;
}
自此,完成了界面二跳转至界面一的数据传递。
使用代理传递数据
不写代理的.h文件
AddTime *t_vc = [[AddTime alloc] initWithNibName:@"AddTime" bundle:nil];
t_vc.delegate = (id<AddTimeDelegate>)self;
t_vc.timeArr = timeArr;
t_vc.maxCount = 2;
[self.navigationController pushViewController:t_vc animated:YES];
-(void)getTime:(NSString *)Time
{
[timeArr addObject:Time];
[_tableView reloadData];
}
在界面二 .h
@protocol AddTimeDelegate;
@interface AddTime : BaseViewController
@property(nonatomic,weak)id<AddTimeDelegate> delegate;
@property(nonatomic,strong)NSMutableArray *timeArr;
@property(nonatomic,assign)NSInteger maxCount;
@property(nonatomic,assign)NSInteger type;
@end
@protocol AddTimeDelegate<NSObject>
-(void)getTime:(NSString *)Time;
@end
[self.delegate getTime:t_str];
[self.navigationController popViewControllerAnimated:YES];
拥有较多代理的.h文件
ViewController.h
#import <UIKit/UIKit.h>
#import "PassValueDelegate.h"
//第一个窗口遵守PassValueDelegate
@interface ViewController : UIViewController<PassValueDelegate>
@property (retain, nonatomic) IBOutlet UILabel *nameLabel;
@property (retain, nonatomic) IBOutlet UILabel *ageLabel;
@property (retain, nonatomic) IBOutlet UILabel *gendarLabel;
- (IBAction)openBtnClicked:(id)sender;
@end
ViewController.m
//实现协议,在第一个窗口显示在第二个窗口输入的值,类似Android中的onActivityResult方法
-(void)passValue:(UserEntity *)value
{
self.nameLabel.text = value.userName;
self.ageLabel.text = [NSString stringWithFormat:@"%d",value.age];
self.gendarLabel.text = value.gendar;
}
//点击进入第二个窗口的方法
- (IBAction)openBtnClicked:(id)sender {
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:[NSBundle mainBundle]];
//设置第二个窗口中的delegate为第一个窗口的self
secondView.delegate = self;
[self.navigationController pushViewController:secondView animated:YES];
[secondView release];
}
SecondViewController.h
#import <UIKit/UIKit.h>
#import "PassValueDelegate.h"
@interface SecondViewController : UIViewController
@property (retain, nonatomic) IBOutlet UITextField *nameTextField;
@property (retain, nonatomic) IBOutlet UITextField *ageTextFiled;
@property (retain, nonatomic) IBOutlet UITextField *gendarTextField;
//这里用assign而不用retain是为了防止引起循环引用。
@property(nonatomic,assign) NSObject<PassValueDelegate> *delegate;
- (IBAction)okBtnClicked:(id)sender;
- (IBAction)closeKeyboard:(id)sender;
@end
SecondViewController.m
- (IBAction)okBtnClicked:(id)sender {
UserEntity *userEntity = [[UserEntity alloc] init];
userEntity.userName = self.nameTextField.text;
userEntity.gendar = self.gendarTextField.text;
userEntity.age = [self.ageTextFiled.text intValue];
//通过委托协议传值
[self.delegate passValue:userEntity];
//退回到第一个窗口
[self.navigationController popViewControllerAnimated:YES];
[userEntity release];
}
/*单击屏幕其他区域关闭键盘的方法
实现方法是:首先选中xib文件的view,设置class为UIControl
然后在事件中选择Touch Down拖线到.h文件中声明该方法,最后实现下面即可
*/
- (IBAction)closeKeyboard:(id)sender {
[self.nameTextField resignFirstResponder];
[self.ageTextFiled resignFirstResponder];
[self.gendarTextField resignFirstResponder];
}
PassValueDelegate.h
#import <Foundation/Foundation.h>
@class UserEntity;
@protocol PassValueDelegate <NSObject>
-(void)passValue:(UserEntity *)value;
@end
使用通知Notification
要在代码中的两个不相关的模块中传递消息时,通知机制是非常好的工具。通知机制广播消息,当消息内容丰富而且无需指望接受者一定要关注的话这一招特别有用。
通知可以用来发送任意消息,甚至可以包含一个userInfo字典。你可以继承NSNotification 写一个自己的通知类类自定义行为,通知的独特之处在于,发送者和接受者不需要相互知道对方,所以通知可以被用来在不同的相隔很远的模块之间传递消息。这就意味着这种消息的传递是单向的,我们不能回复通知。
这是一种“同步的”消息通知机制,观察者只要向消息中心注册,即可接受其他对象发送来的消息,消息发送者和接收者两者可以互相一无所知,完全解耦。
这种消息通知机制可以应用于任何对象,观察者可以有多个,所以消息具有广播的性质。需要注意的是,观察者向消息中心注册以后,在不需要接收消息是需要从消息中心移除。
这种消息传递机制是典型的观察者模式。
使用这种消息机制的步骤:
1.观察者注册消息通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getUserProfileSuccess:) name:@"Notification_GetUserProfileSuccess" object:nil];
- notificationobserver观察者:self
- notificationselector处理消息的方法名:getUserProfileSuccess
- notificationName消息通知的名字:Notification_GetUserProfileSuccess
- notificationSender消息发送者:表示接收哪个发送者的通知,为nil则接收所有发送者的通知
2.发送消息通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"Notification_GetUserProfileSuccess"
object:userProfile userInfo:nil];
- notificationName 消息通知的名字: Notification_GetUserProfileSuccess
- notificationSender 消息发送者: userProfile
3.观察者处理消息
- (void) getUserProfileSuccess: (NSNotification*) aNotification
{
self.userProfile = [aNotification object];
lblName.text = self.userProfile.Name;
lblEENO.text = self.userProfile.EENO;
lblNric.text = self.userProfile.NRIC;
lblBirthday.text =self.userProfile.Birthday;
lblHireDate.text = self.userProfile.Hiredate;
txtMobilePhone.text = self.userProfile.Mobile;
txtEmail.text = self.userProfile.Email;
}
NSNotification 接受到的消息信息,主要含:
- Name: 消息名称 Notification_GetUserProfileSuccess
- object: 消息发送者 userProfile
- userInfo: 消息传递的数据信息
4.观察者注销,移除消息观察者
虽然在 IOS 用上 ARC 后,不显示移除 NSNotification Observer 也不会出错,但是这是一个很不好的习惯,不利于性能和内存。
注销观察者有2个方法:
a. 最优的方法,在 UIViewController.m 中:
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
b. 单个移除:
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"Notification_GetUserProfileSuccess" object:nil];
注:按照我所理解,先在界面一注册一个观察者,这个观察者可以改变当前页面的数据,然后在第二个界面发送通知,让界面一接收通知并且执行事件。这说明不能直接从界面一去改变界面二的数据,因为必须先注册后接收。要想改变二,就要先进入界面二注册,此时肯定是不会传递数据的,因为还未注册。