一、屬性傳值
從前向后
假設(shè)A為第一個(gè)視圖控制器贺待,B為第二個(gè)視圖控制器
在A中導(dǎo)入B的.h文件
場(chǎng)景:A向B傳值
第一步:在B的.h中定義一個(gè)content屬性
@interface SecondViewController : UIViewController
@property(nonatomic,copy)NSString *contents;
@end
第二步:在點(diǎn)擊A中的按鈕的方法里面給B的content屬性賦值
-(void)buttonAction:(UIButton *)button
{
NSLog(@"進(jìn)入第二頁");
SecondViewController *secondVC =
[[SecondViewController alloc] init];
secondVC.contents = self.label.text;
[self.navigationController pushViewController:secondVC animated:YES];
[secondVC release];
}
第三步:在B中使用content的屬性給相應(yīng)的控件賦值
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = self.contents;
}
二徽曲、代理傳值
代理傳值使用在兩個(gè)界面?zhèn)髦档臅r(shí)候,從后向前傳值麸塞。
假設(shè)A為第一個(gè)視圖控制器秃臣,B為第二個(gè)視圖控制器
場(chǎng)景:B向A傳值
第一步:首先在B的.h文件中聲明協(xié)議和協(xié)議方法
第二步:在B的.h中聲明一個(gè)協(xié)議屬性,這里要注意用assign或weak修飾哪工,
weak和assign是一種“非擁有關(guān)系”的指針奥此,通過這兩種修飾符修飾的指針變量,都不會(huì)改變被引用對(duì)象的引用計(jì)數(shù)雁比。但是在一個(gè)對(duì)象被釋放后稚虎,weak會(huì)自動(dòng)將指針指向nil,而assign則不會(huì)偎捎。所以蠢终,似乎用weak更安全些。
@property (nonatomic茴她,assign)id <協(xié)議名>delegate寻拂;
#pragma mark 這里是B的.h
#import <UIKit/UIKit.h>
@protocol CustomTabBarDelegate <NSObject>
//把btn的tag傳出去的方法
-(void)selectedIndexWithTag:(NSInteger)tag;
@end
@interface CustomTabBarView : UIView
//聲明一個(gè)協(xié)議屬性delegate
@property (nonatomic,assign)id <CustomTabBarDelegate>delegate;
@end
第三步:在B即將POP回前一個(gè)界面的時(shí)候,在pop方法的上一行使用協(xié)議方法傳遞數(shù)據(jù)
[self.delegate 協(xié)議方法名稱:(參數(shù)丈牢,也就是要傳回的數(shù)據(jù))
#pragma mark 這里是B的.m
// 判斷在指定的代理類中是否實(shí)現(xiàn)了該協(xié)議方法
// 確保執(zhí)行時(shí)無此方法時(shí)不崩潰
if([self.delegate respondsToSelector:@selector(selectedIndexWithTag:)])
{
//執(zhí)行代理方法
[self.delegate selectedIndexWithTag:(sender.tag - 1000)];
}
else
{
NSLog(@"selectIndexWithTag該方法沒有實(shí)現(xiàn)");
}
第四步:在A的.m中祭钉,在push到B界面的push方法之前,B對(duì)象的初始化之后己沛,指定A對(duì)象為B對(duì)象的代理
(B對(duì)象).delegate = self;
此時(shí)會(huì)有黃色警告慌核,沒有遵守協(xié)議
#pragma mark A的.m中
//指定代理,B就是customView
customView.delegate = self;
第五步:在A的延展或者A的.h文件中導(dǎo)入?yún)f(xié)議<協(xié)議名稱>
#pragma mark A的.m的延展里 申尼, A就是RootTabBarController
//導(dǎo)入?yún)f(xié)議
@interface RootTabBarController ()<CustomTabBarDelegate>
@end
第六步:在A的.m中實(shí)現(xiàn)協(xié)議方法垮卓,取得參數(shù)中的值,呈現(xiàn)在當(dāng)前界面上
#pragma mark A的.m
//實(shí)現(xiàn)代理方法晶姊,這里就可以使用從B傳來的值了
- (void)selectedIndexWithTag:(NSInteger)tag
{
self.selectedIndex = tag;
}
三扒接、block傳值
這里就不具體講block是怎么回事了,這是OC的基礎(chǔ)內(nèi)容。
block就是一塊代碼片段钾怔,類似于函數(shù)但是block可以作為參數(shù)進(jìn)行傳遞
第一步:
在B的.h中重定義一個(gè)block碱呼,用這個(gè)重定義的block類型聲明一個(gè)類的屬性
這里要注意用copy修飾block屬性
#pragma mark B的.h
#import <UIKit/UIKit.h>
//block傳值
//重命名一個(gè)有參無返回值的block類型
typedef void(^passValue)(NSInteger tag);
@interface CustomTabBarView : UIView
//用這個(gè)block類型定義一個(gè)屬性
@property (nonatomic,copy)passValue passValueTag;
@end
第二步:
在B的.m的返回方法中調(diào)用block的方法
#pragma mark B的.m的返回方法中
nbsp;//調(diào)用block方法
self.passValueTag(sender.tag - 1000);
第三步:
在A的.m中創(chuàng)建B的實(shí)例的地方,為B的block屬性賦值宗侦,也就是說愚臀,寫好這個(gè)block中的內(nèi)容,類似于給B的某一個(gè)屬性賦初值
//設(shè)置block內(nèi)容
customView.passValueTag = ^(NSInteger tag)
{
self.selectedIndex = tag;
};
這里只有三步矾利,比代理的方法簡單了不少
下面是實(shí)現(xiàn)效果
第一頁有個(gè)Label姑裂,在第二頁的輸入框輸入文字,就可以顯示在第一頁的label上男旗,實(shí)現(xiàn)了從后向前的傳值
沒有引用局部變量的block內(nèi)存存儲(chǔ)在全局區(qū)
沒有引用局部變量的block內(nèi)存存儲(chǔ)在全局區(qū)
引用了局部變量的block內(nèi)存存儲(chǔ)在棧區(qū)
當(dāng)對(duì)block進(jìn)行copy操作的時(shí)候blcok的內(nèi)存在堆區(qū)
block的循環(huán)引用問題
當(dāng)block是self的一個(gè)屬性的時(shí)候
self.circleBlock = ^() { my_self.navigationItem.title = @"asd"; };
會(huì)導(dǎo)致self的引用計(jì)數(shù)+1舶斧,最終導(dǎo)致循環(huán)引用
在arc下使用__weak修飾變量防止循環(huán)引用
在非arc下使用__block修飾變量防止循環(huán)引用
四、單例傳值
單例傳值基本思路是創(chuàng)建一個(gè)SingleTon類察皇,里面定義一個(gè)要傳的值的屬性茴厉,再聲明一個(gè)share類方法,在類方法中用static定義類的實(shí)例變量什荣,讓它只初始化一次矾缓。
這樣凡是導(dǎo)入這個(gè)SingleTon類的文件都可以通過share方法聲明一個(gè)實(shí)例變量,從變量中拿到它的屬性稻爬,這個(gè)屬性是地址唯一的嗜闻,也就是說,大家拿到的都一樣桅锄,一處變化琉雳,任何位置拿到的這個(gè)值都變化。
創(chuàng)建SingleTon類
SingleTon.h
#import <Foundation/Foundation.h>
@interface SingleTon : NSObject
//傳值的具體屬性
@property (nonatomic,retain)NSString *passValue;
//一般單例是類方法來創(chuàng)建
+(SingleTon*)sharedSingleTon;
@end
SingleTon.m
#import "SingleTon.h"
@implementation SingleTon
+(SingleTon *)sharedSingleTon
{
//static 只賦值一次
static SingleTon *singleTon = nil;
//線程鎖竞滓,保證同時(shí)只有一個(gè)線程訪問
@synchronized(self) {
if (!singleTon) {
singleTon = [[SingleTon alloc]init];
}
}
return singleTon;
}
@end
//GCD方法創(chuàng)建單例
+(XMPPTools *)sharedXMPPTool
{
static XMPPTools *xmppTools = nil;
//GCD方式創(chuàng)建單例
static dispatch_once_t onceToker;
_dispatch_once(&onceToker, ^{
xmppTools = [[XMPPTools alloc]init];
});
return xmppTools;
}
這次把代碼貼全點(diǎn)
AppDelegate.h
#import "AppDelegate.h"
#import "RootViewController.h"
#import "SecondViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
RootViewController *rootVC = [[RootViewController alloc]init];
//創(chuàng)建導(dǎo)航控制器
UINavigationController *naviagtionC = [[UINavigationController alloc]initWithRootViewController:rootVC];
self.window.rootViewController = naviagtionC;
return YES;
}
用的時(shí)候在兩個(gè)ViewController文件中導(dǎo)入SingleTon.h
RootViewController.m
#import "RootViewController.h"
#import "SingleTon.h"
#import "SecondViewController.h"
@interface RootViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic,retain)UITextField* myTextField;
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"第一頁";
//添加UItextField
_myTextField = [[UITextField alloc]initWithFrame:CGRectMake((414-200)/2, 200, 200, 40)];
_myTextField.borderStyle = UITextBorderStyleLine;
_myTextField.placeholder = @"input";
//添加按鈕
UIButton *myBtn = [UIButton buttonWithType:UIButtonTypeSystem];
myBtn.frame = CGRectMake((414-100)/2, 300, 100, 100);
[myBtn setTitle:@"確定" forState:UIControlStateNormal];
myBtn.layer.cornerRadius = 50;
myBtn.layer.masksToBounds = YES;
myBtn.backgroundColor = [UIColor colorWithRed:200/255.0 green:233/255.0 blue:160/255.0 alpha:1];
//添加按鈕方法
[myBtn addTarget:self action:@selector(jumpToSecondVC:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:myBtn];
[self.view addSubview:_myTextField];
}
//重復(fù)調(diào)用的方法咐吼,再返回時(shí)用單例的值給標(biāo)題
-(void)viewWillAppear:(BOOL)animated
{
SingleTon *singleTon = [SingleTon sharedSingleTon];
if (singleTon.passValue.length) {
self.navigationItem.title = singleTon.passValue;
}
}
-(void)jumpToSecondVC:(UIButton*)sender
{
NSLog(@"tap btn");
SingleTon *mySingleTon = [SingleTon sharedSingleTon];
//把輸入框的值給單例的屬性
mySingleTon.passValue = _myTextField.text;
SecondViewController *secondVC = [[SecondViewController alloc]init];
[self.navigationController pushViewController:secondVC animated:YES];
}
SecondViewController.m
#import "SecondViewController.h"
#import "SingleTon.h"
@interface SecondViewController ()
@property (nonatomic,retain)UITextView *myTextView;//
@property (nonatomic,retain)UITextField *testTextField;
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"第二頁";
SingleTon *mySingleTon = [SingleTon sharedSingleTon];
self.navigationItem.title = mySingleTon.passValue;
_testTextField = [[UITextField alloc]initWithFrame:CGRectMake((414-200)/2, 300, 200, 40)];
[self.view addSubview:_testTextField];
_testTextField.placeholder = @"input";
mySingleTon.passValue = _testTextField.text;
}
//view即將消失時(shí)吹缔,也就是返回前商佑,賦值給單例
-(void)viewWillDisappear:(BOOL)animated
{
SingleTon *mySingleTon = [SingleTon sharedSingleTon];
mySingleTon.passValue = _myTextField.text;
}