六大傳值--(屬性/代理/通知/KVO/KVC/Tag/單例/Block/全局)
先創建兩個ViewController:
1,先在Appdelegate.m里設置一個AViewController.m 為rootViewController,并創建一個BViewController
在AViewController.m中導入BViewController.h,,,創建一個SingleOne繼承于NSObject作為單例類
import "AViewController.h"
import "BViewController.h"
//單例
import "SingleOne.h"
//代理傳值,遵循協議Nextprotocol
@interface AViewController ()<UITextFieldDelegate,Nextprotocol>
{
BViewController *bView;
}
@end
@implementation AViewController
-
(void)viewDidLoad {
[superviewDidLoad];self.title =@"AViewController";
self.view.backgroundColor = [UIColorwhiteColor];//作一個跳轉button
UIBarButtonItem *item = [[UIBarButtonItemalloc]initWithTitle:@"跳轉"style:UIBarButtonItemStylePlaintarget:selfaction:@selector(touchAction:)];
self.navigationItem.rightBarButtonItem = item;
//聲明一個aTextFiled
UITextField *aTextField = [[UITextFieldalloc]initWithFrame:CGRectMake([UIScreenmainScreen].bounds.size.width/2-150, [UIScreenmainScreen].bounds.size.height/2-25,300, 30)];
aTextField.layer.borderWidth =2;
aTextField.layer.borderColor = [UIColorgrayColor].CGColor;
aTextField.layer.masksToBounds =YES;
aTextField.tag = 1000;
aTextField.delegate = self;
[self.viewaddSubview:aTextField];
// aTextField.text = @"李濤你個混蛋";
//反正是KVO時就一定要放在viewdidLoad這里,不會跳兩第二次時會報錯,說這個bView已經消亡了但還有人在監聽它
bView = [[BViewController alloc]init];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
-(void)touchAction:(UIButton *)sender
{
//用tag傳值
UITextField *aTextFiled = (UITextField *)[self.viewviewWithTag:1000];
// NSLog(@"aTextFiled.text = %@",aTextFiled.text);
// BViewController *bView = [[BViewControlleralloc]init];
/*-------------------單例傳值:從A---->>B ----------------------*/
SingleOne *onlyOne = [SingleOneshareData];
//讓單例作為中介去接收A頁面要傳的值,
onlyOne.value = aTextFiled.text;
/*-------------------block傳值:從B---->>A -------------------*/
[bView setMblock:^(NSString *string){ //注意類型,也可以用id
aTextFiled.text = string;
}];
bView.mblock = ^(id string){
aTextFiled.text = string;
};
/*---------------------屬性傳值:從A--->>B --------------------*/
bView.text1 = aTextFiled.text;
/*---------------------KVC傳值-------------------------*/
[bView setValue:aTextFiled.textforKey:@"_name"];
[bView setValue:aTextFiled.textforKey:bView.text1]; //或者
/*---------------------通知傳值 B--->>A ------------------------*/
//
如果是從A傳到B的話,這里寫發通知,B.m里要創建一個init方法,在里面寫監聽并在里面創建接收容器才能成功(因為程序先執行init方法再到viewDidLoad方法,當傳值過去時在init就開始監聽,如果這里沒有創建textField接收,那就傳不過去了,所以要在init里同時創建接收器(生命周期的問題));
//這里是從B到A:注冊監聽:從B傳到A話因為從A跳轉到B時已經創建好A了,所以
[[NSNotificationCenterdefaultCenter] addObserver:selfselector:@selector(aAction:)name:@"amessage"object:nil];
/*---------------------代理傳值 B--->>A -------------------*/
bView.delegate = self; //設置代理
/---------------------KVO回傳值 B--->>A-------------------/
//注冊觀察者:如果用了KVO一定要把bView的初始化放在上面的viewDidLoad里
[bView addObserver:self forKeyPath:@"test1" options:NSKeyValueObservingOptionNew context:nil];
//把更改之后的值提供給觀察者的回調方法
[self.navigationControllerpushViewController:bView animated:YES];
}
pragma mark============代理傳值:實現協議方法==============
-(void)transferString:(NSString *)string
{
UITextField *aTextField = (UITextField *)[self.viewviewWithTag:1000];
aTextField.text = string;
}
pragma mark -----------通知回調方法實現--------------
-(void)aAction:(NSNotification *)sender
{
UITextField *aField = (UITextField *)[self.viewviewWithTag:1000];
aField.text = sender.userInfo[@"akey"];
}
pragma mark ------------- KVO回調 ------------------
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
UITextField *aTextField = (UITextField *)[self.view viewWithTag:1000];
//此處監聽鍵路徑key的值有沒有發生變化
if ([keyPath isEqualToString:@"text1"]) { //如果觀察的對象是text1
aTextField.text = bView.text1;
}
}
//移除通知的監聽者 和 KVO的觀察者(如果不移除,會變成野指針)
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"amessage" object:nil]; //移除通知監聽者
[bView removeObserver:self forKeyPath:@"text1"]; //移除KVO觀察者
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
BVIewController.h里
//
// BViewController.h
// test傳值
//
// Created by ibokan on 16/3/16.
// Copyright ? 2016年譚其偉. All rights reserved.
//
import <UIKit/UIKit.h>
pragma mark ======Block傳值=========
typedef void(^TransferValue) (NSString *string);
pragma mark---------代理傳值-------------
//聲明一個協議
@protocol Nextprotocol <NSObject>
//協議里的方法(讓遵循該協議的類實現,自己不實現)
-(void)transferString:(NSString *)string;
@end
@interface BViewController : UIViewController
{
//KVC傳值需要有一個實例變量作為key
NSString *_name;
}
//把block作為屬性
@property(nonatomic,copy)TransferValue mblock;
//屬性傳值
@property(nonatomic,readwrite,strong)NSString *text1;
pragma mark---------代理傳值-------------
//有一個遵循協議的代理屬性
@property(nonatomic,readwrite,strong)id<Nextprotocol>delegate;
@end
BViewController.m里
//
// BViewController.m
// test傳值
//
// Created by ibokan on 16/3/16.
// Copyright ? 2016年譚其偉. All rights reserved.
//
import "BViewController.h"
//單例
import "SingleOne.h"
@interface BViewController ()<UITextFieldDelegate>
{
UITextField *bTextFiled;
}
@end
@implementation BViewController
-
(void)viewDidLoad {
[superviewDidLoad];self.title =@"BViewController";
self.view.backgroundColor = [UIColorredColor];
//聲明一個返回button
UIButton *aButton = [UIButtonbuttonWithType:UIButtonTypeCustom];
aButton.frame = CGRectMake([UIScreen mainScreen].bounds.size.width/2-50,150, 100, 30);
[aButton setTitleColor:[UIColorblackColor] forState:UIControlStateNormal];
[aButton addTarget:selfaction:@selector(backAction:)forControlEvents:UIControlEventTouchUpInside];
[aButton setTitle:@"返回"forState:UIControlStateNormal];
[self.viewaddSubview:aButton];
//使用全局傳值:聲明一個bTextFiled
bTextFiled = [[UITextFieldalloc]initWithFrame:CGRectMake([UIScreenmainScreen].bounds.size.width/2-150, [UIScreen mainScreen].bounds.size.height/2-100,300, 30)];
bTextFiled.layer.borderColor = [UIColorblackColor].CGColor;
bTextFiled.layer.borderWidth =2;
//_btextFiled.delegate = self;
bTextFiled.text = [NSStringstring]; //相當于nil
bTextFiled.layer.masksToBounds =YES;
[self.viewaddSubview:bTextFiled];
pragma mark ------單例傳值接收:再間接傳給B頁面-----------------
bTextFiled.text = [SingleOneshareData].value;
pragma mark ++++++++++++屬性傳值++++++++++++++++
bTextFiled.text =self.text1;
//KVC傳值
self.text1 =_name;
bTextFiled.text =self.text1;
pragma mark ==============通知傳值:回傳=====================
//發送通知
[[NSNotificationCenterdefaultCenter] postNotificationName:@"amessage"object:selfuserInfo:@{@"akey":bTextFiled.text}];
}
-(void)backAction:(UIButton *)sender
{
/*-------------block傳值要寫在方法里----------------*/
_mblock(bTextFiled.text);
self.mblock(bTextFiled.text);
/*---------------代理傳值-------------------------*/
if (self.delegate && [self.delegateconformsToProtocol:@protocol(Nextprotocol)]) {
[self.delegatetransferString:bTextFiled.text];
}
[self.navigationControllerpopViewControllerAnimated:YES];
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
單例類:
SingleOne.h
// SingleOne.h
// test傳值
//
// Created by ibokan on 16/3/16.
// Copyright ? 2016年譚其偉. All rights reserved.
//
import <Foundation/Foundation.h>
@interface SingleOne : NSObject
//創建一個單例//如果在單線程里可以用nonatomic,如果在多線程里一定要用atomic,保證是只有一個在調用,不然在多線程里面如果多個方法調用修改單例類里的屬性時會沖突
@property(atomic,readwrite,strong)NSString *value;
//聲明一個類方法
+(SingleOne *)shareData;
@end
SingleOne.m里
//
// SingleOne.m
// test傳值
//
// Created by ibokan on 16/3/16.
// Copyright ? 2016年譚其偉. All rights reserved.
//
import "SingleOne.h"
//聲明一個表態實例對象,讓其為空
static SingleOne *onlyOne =nil;
@implementation SingleOne
//實現方法,判斷是否為空,是就創建一個全局實例給它
+(SingleOne *)shareData
{
if (onlyOne ==nil) {
onlyOne = [[SingleOnealloc]init];
}
returnonlyOne;
}
//避免alloc/new創建新的實例變量--->增加一個互斥鎖
+(id)allocWithZone:(struct_NSZone *)zone
{
@synchronized(self) {
if (onlyOne ==nil) {
onlyOne = [superallocWithZone:zone];
}
}
returnonlyOne;
}
//避免copy,需要實現NSCopying協議
-(id)copyWithZone:(NSZone *)zone
{
return self;
}
@end