- 前言
本文用最基本的界面通訊(傳個(gè)字符串)來舉例子, 傳遞時(shí)要分清楚, 控制器出現(xiàn)的先后順序.(當(dāng)傳遞數(shù)據(jù)時(shí), 下一個(gè)界面都沒有初始化就肯定不行) 協(xié)議和Block不僅可以傳遞數(shù)據(jù), 還可以調(diào)用其他頁面的函數(shù)方法.
屬性傳值
- 例如:第一頁內(nèi)容, 傳給后一頁
1. 因?yàn)橐獋鬟f給下一頁, 下一頁一定要有一個(gè)儲(chǔ)存的載體, 所以聲明一個(gè)屬性
@interface SecondViewController ()
@property (nonatomic, copy)NSString *string;
@end
2. push下一頁時(shí)候賦值
@implementation FirstViewController
- (void)didClicked:(UIButton *)sender
{
SecondViewController *svc = [[SecondViewController alloc]init];
svc.string = @"蘋果";
[self.navigationController pushViewController:svc animated:YES];
}
@end
3. 在下一頁secondViewController.h中就可以打印出來了
@implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"%@", self.string)
}
@end
- 優(yōu)點(diǎn) 最簡單的傳值方法
- 缺點(diǎn) 只能從前往后傳值
代理協(xié)議
- 完成協(xié)議傳值大致分6步
- 聲明協(xié)議
- 聲明屬性 (設(shè)置代理人屬性)
- 執(zhí)行協(xié)議方法 (何時(shí)觸發(fā)方法)
- 簽協(xié)議 (代理人引頭文件)
- 指定代理人 (.delegate = self)
- 實(shí)現(xiàn)方法
- SecondViewController.h
//在SecondViewController.h中
//聲明協(xié)議和代理人的屬性
@protocol secondViewControllerDelegate <NSObject>//第1步
-(void)passString:(NSString *)string;
@end
@interface secondViewController : UIViewController
//必須是assign,其他會(huì)有循環(huán)引用問題
@property (nonatomic, assign)id<secondViewControllerDelegate>delegate;//第2步
@end
//在SecondViewController.m中
@implementation secondViewController
-(void)ViewDidLoad
{
//第3步 這個(gè)是控制何時(shí)觸發(fā)協(xié)議方法的,當(dāng)程序走到這行代碼時(shí),程序會(huì)跳轉(zhuǎn)到代理人界面,調(diào)用代理人頁面下的協(xié)議方法
[self.delegate passString:@"蘋果"];
}
@end
- FirstViewController.m
// 引頭文件和簽協(xié)議(必須得有這兩步)//第4步
@interface FirstViewController ()< secondViewControllerDelegate >
@end
@implementation FirstViewController
-(void)ViewDidLoad
{
SecondViewController *vc = [[SecondViewController alloc]init];
vc.delegate = self;//第5步
//設(shè)置的代理人必須是當(dāng)前的VC!!!!!!!!!!!!!!!!!!!!
}
-(void)passString:(NSString *)string//第6步 實(shí)現(xiàn)協(xié)議方法
{
UITextField *textField = [[UITextField alloc]init];
textField.text = string;//這時(shí)string參數(shù)就是傳過來的"蘋果"
}
@end
- 優(yōu)點(diǎn): 好理解, 最常用的一種設(shè)計(jì)模式, 可以解決代碼的耦合性
- 缺點(diǎn): 寫的麻煩
Block傳值
(1). block的寫法及分類
- Block的寫法: 返回值類型(^起個(gè)名字)(參數(shù)類型, 參數(shù)類型 *) = ^(參數(shù)類型, 參數(shù)類型 *){具體實(shí)現(xiàn)的方法};
- Block的四種類型的定義
- 1.無參數(shù)無返回值
void(^block1)(void) = ^(void){...};
- 2.有參數(shù)無返回值
void(^block2)(int age, NSString *string) = ^(int age, NSString *string) {...};
- 3.有返回值,無參數(shù)
int (^block3)(void) = ^(void){ return 3; }
- 4.有返回值,有參數(shù)
NSInteger (^block4)(NSInteger *) = ^(NSInteger num) { return num; };
(2).Block傳值
- 傳值頁面聲明block屬性
//在想要回傳的界面中定義,block必須用copy來修飾(*注:SecondViewController.h中聲明)
//@property (nonatomic, copy)NSArray *(^Block)(NSString *string);后面必須兩個(gè)括號
@property (nonatomic, copy)void(^Block)(NSString *string);
- 傳值頁面調(diào)用block, 把"蘋果"傳過去
這個(gè)就相當(dāng)于屬性的get方法, 會(huì)執(zhí)行- (void(^)(NSString *))Block
self.Block(@"蘋果");
//當(dāng)程序走到這行代碼時(shí), 程序會(huì)自動(dòng)跳轉(zhuǎn)到block內(nèi)部, 執(zhí)行下面的方法
- 被傳值的頁面block參數(shù)就會(huì)有值了
//初始化一個(gè)secondVC對象
SecondViewController *secondVC. = [[SecondViewController alloc]init];
這個(gè)就相當(dāng)于屬性的set方法 會(huì)走 - (void)setBlock:(void(^)(NSString *))Block
secondVC.Block = ^(NSString *string)
{
firstVC.label.text = string;
// 這時(shí)string這個(gè)參數(shù)就是"蘋果"了
};
//Block與屬性區(qū)別, 就是可以將代碼當(dāng)參數(shù), 后期調(diào)用block時(shí), 被保存的代碼就會(huì)執(zhí)行, 跟協(xié)議傳值大同小異
//關(guān)于block的內(nèi)存問題
//1.如果要使用block作為一個(gè)屬性, 必須用copy
//2.為了防止循環(huán)引用, 可以用弱指針代替
//ARM寫法: __weak typeof( 類型 *) weakSelf = self;
//MRC寫法: __ block typeof( 類型 *) weakSelf = self;