IOSBlock之頁(yè)面之間的傳值問(wèn)題
一.字典 數(shù)組和字符串的傳值
blcok的基本格式:返回值類(lèi)型(^block變量名)(形參列表) = ^(形參列表) {
};
調(diào)用Block保存的代碼
block變量名(實(shí)參);
默認(rèn)情況下,Block內(nèi)部不能修改外面的局部變量
Block內(nèi)部可以修改使用__block修飾的局部變量
void (^myBlock1)(void);? //無(wú)返回值,無(wú)參數(shù)
void (^myBlock2)(NSObject, int); //有返回值,有參數(shù)
NSString* (^myBlock3)(NSString* name, int age); //有返回值和參數(shù),并且在參數(shù)類(lèi)型后面加入了參數(shù)名(僅為可讀性
有參數(shù)無(wú)返回值的Block
**
*? 調(diào)用這個(gè)block進(jìn)行兩個(gè)參數(shù)相加
*
*? @param int 參數(shù)A
*? @param int 參數(shù)B
*
*? @return 無(wú)返回值
*/
void (^sumBlock)(int ,int ) = ^(int a,int b){
NSLog(@"%d + %d = %d",a,b,a+b);
};
/**
*? 調(diào)用這個(gè)sumBlock的Block,得到的結(jié)果是20
*/
sumBlock(10,10);
有參數(shù)有返回值的Block
/**
*? 有參數(shù)有返回值
*
*? @param NSString 字符串1
*? @param NSString 字符串2
*
*? @return 返回拼接好的字符串3
*/
NSString* (^logBlock)(NSString *,NSString *) = ^(NSString * str1,NSString *str2){
return [NSString stringWithFormat:@"%@%@",str1,str2];
};
//調(diào)用logBlock,輸出的是 我是Block
NSLog(@"%@", logBlock(@"我是",@"Block"));
1.我發(fā)現(xiàn)字符串傳值的話(huà)比較容易但是字典傳值的時(shí)候需要將字典中的值取出來(lái)進(jìn)行傳值或者進(jìn)行字典轉(zhuǎn)模型進(jìn)行傳值也比較容易,總之來(lái)說(shuō)字符串傳值很輕松的 也解決了很多傳值的bug問(wèn)題.
其中代碼是這么實(shí)現(xiàn)的
第二個(gè)控制器的.h中寫(xiě)出代碼塊和代碼塊需要實(shí)現(xiàn)的屬性
TWOViewCtroll.h中
typedef void (^ReturnTextBlock)(NSString *showText);
@interface TWOViewCtroll : UIViewController
@property (nonatomic, copy) ReturnTextBlock returnTextBlock;
- (void)returnText:(ReturnTextBlock)block;
在.m中
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//? ? lable = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
//? ? lable.text = @"taishabi";
//? ? lable.backgroundColor = [UIColor blueColor];
//? ? lable.textColor = [UIColor blackColor];
//? ? [self.view addSubview:lable];
//? ? dic = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
//? ? ? ? ? @"abc",@"name",
//? ? ? ? ? @"12",@"age",
//? ? ? ? ? @"老了",@"old"
//? ? ? ? ? , nil];
arr = [NSMutableArray arrayWithObjects:@"123",@"456",@"789",@"101112",@"131415", nil];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click:)];
[self.view addGestureRecognizer:tap];
}
-(void)click:(UITapGestureRecognizer *)tap
{
[self dismissViewControllerAnimated:NO completion:nil];
}
- (void)returnText:(ReturnTextBlock)block {
self.returnTextBlock = block;
}
- (void)viewWillDisappear:(BOOL)animated {
if (self.returnTextBlock != nil) {
self.returnTextBlock([arr objectAtIndex:0]);
}}
在第一個(gè)界面需要代碼
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
lable = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
//? ? lable.text = @"123456789";
lable.backgroundColor = [UIColor blueColor];
lable.textColor = [UIColor blackColor];
[self.view addSubview:lable];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click:)];
[self.view addGestureRecognizer:tap];
}
-(void)click:(UITapGestureRecognizer *)tap
{
TWOViewCtroll *two = [[TWOViewCtroll alloc] init];
[two returnText:^(NSString *showText) {
lable.text = showText;
}];
[self presentViewController:two animated:NO completion:nil];
}
2.在這段代碼中可以看出我們創(chuàng)建正常的字符串傳值的話(huà)可以很輕松的進(jìn)行傳值在字典中可以將字典的所有key值進(jìn)行便利出來(lái)for (<#type *object#> in <#collection#>) {
<#statements#>
}
在這里將所有字典key值全部取出放入字符串中便可實(shí)現(xiàn)輕松傳值,如果我們?cè)陂_(kāi)發(fā)中會(huì)遇到各種各樣的字典和json文件我們可以將json文件解析出來(lái)之后進(jìn)行modle轉(zhuǎn)模型便可實(shí)現(xiàn)輕松傳值
3.我們?cè)谶@段代碼中可以發(fā)現(xiàn)我們的數(shù)組中的值也是通過(guò)下標(biāo)進(jìn)行取出的,這個(gè)道理和字典去key值是一樣的都是將值取出來(lái)然后變成字符串屬性傳值到新的界面如果很多數(shù)據(jù)的數(shù)組我們便可以是使用for (<#type *object#> in <#collection#>) {
<#statements#>
}
來(lái)進(jìn)行遍歷了然后便可輕松地傳值到新的界面了
二.block的特性
以上便是block的簡(jiǎn)單結(jié)構(gòu)了不過(guò)blcok的結(jié)構(gòu)很多這只是其中一種
1.blcok傳值過(guò)程需要注意的是我們的傳值類(lèi)型必須和我們自己自定義的類(lèi)型一直否則系統(tǒng)將導(dǎo)致崩潰或者更加困難的傳值消失等等的bug出現(xiàn)
2.代碼塊進(jìn)行排序數(shù)組以及和函數(shù)的關(guān)系等等代碼如下
NSArray *stringArray = [NSArray arrayWithObjects:@"abc 1", @"abc 21", @"abc 12",@"abc 13",@"abc 05",nil];
NSComparator sortBlock = ^(id string1, id string2)
{
return [string1 compare:string2];
};
NSArray *sortArray = [stringArray sortedArrayUsingComparator:sortBlock];
NSLog(@"sortArray:%@", sortArray);
此代碼便是代碼塊進(jìn)行排序的,我們?cè)谶@里可以看出代碼塊的類(lèi)型或者屬性類(lèi)型可以使任意一中的 此處用到的便是升序和降序中的一種NSComparator然后使用新的數(shù)組將其排序后的數(shù)組進(jìn)行歸納
3.代碼塊對(duì)遞歸的調(diào)用
代碼塊想要遞歸調(diào)用,代碼塊變量必須是全局變量或者是靜態(tài)變量,這樣在程序啟動(dòng)的時(shí)候代碼塊變量就初始化了,可以遞歸調(diào)用我們可以將所有的控件或者一些文本內(nèi)容將其遍歷之后將其所有想要改變的東西進(jìn)行改變
4.在代碼塊中可以將代碼塊的屬性使用全局變量或者局部變量進(jìn)行接收從而實(shí)現(xiàn)全局屬性的擴(kuò)展
5.代碼塊的可變數(shù)據(jù)和不可變數(shù)據(jù)的結(jié)果是不同的如果是不可變得如果我們將可變數(shù)據(jù)放在block外面初始化的話(huà)他的內(nèi)容地址不會(huì)進(jìn)行改變?nèi)绻覀儗⒉豢勺償?shù)據(jù)放在外面初始化的話(huà)他的內(nèi)容就會(huì)發(fā)生變化,如果我們將可變和不可以變數(shù)據(jù)在代碼塊中初始化的話(huà)那么他們的地址將不會(huì)發(fā)生任何的變化
6.可以看出在Block內(nèi),不可變對(duì)象的值任然是初始化時(shí)的值,可變對(duì)象的值變成了新值。這是因?yàn)锽lock初始化在前,可變對(duì)象的修改在后;如果顛倒順序,先修改可變對(duì)象的值,再初始化Block,這樣Block就能同步修改后的值了。
7.代碼快傳值不會(huì)將傳進(jìn)去的值進(jìn)行改變
8.代碼塊消耗內(nèi)存比較小,傳值還是推薦代碼塊傳值因?yàn)閷?duì)內(nèi)存要求比較小
9.Block的修飾
ARC情況下
如果用copy修飾Block,該Block就會(huì)存儲(chǔ)在堆空間。則會(huì)對(duì)Block的內(nèi)部對(duì)象進(jìn)行強(qiáng)引用,導(dǎo)致循環(huán)引用。內(nèi)存無(wú)法釋放。
解決方法:
新建一個(gè)指針(__weak typeof(Target) weakTarget = Target )指向Block代碼塊里的對(duì)象,然后用weakTarget進(jìn)行操作。就可以解決循環(huán)引用問(wèn)題。
如果用weak修飾Block,該Block就會(huì)存放在棧空間。不會(huì)出現(xiàn)循環(huán)引用問(wèn)題。
MRC情況下
用copy修飾后,如果要在Block內(nèi)部使用對(duì)象,則需要進(jìn)行(__block typeof(Target) blockTarget = Target )處理。在Block里面用blockTarget進(jìn)行操作。
TWOViewCtroll *two = [[TWOViewCtroll alloc] init];
__weak typeof(TWOViewCtroll) *weakDemo = two;
[weakDemo returnText:^(NSString *showText) {
lable.text = showText;
}];
解決循環(huán)引用問(wèn)題 但還是存在風(fēng)險(xiǎn)的因?yàn)檫@時(shí)候的block沒(méi)有run這樣就會(huì)導(dǎo)致內(nèi)容改變因?yàn)閮?nèi)存對(duì)象早就被釋放了
如果blcok是常數(shù)的情況下我們需要在變量前面加上 __weak
10.Block是什么?
- 匿名函數(shù)
- 截獲自動(dòng)變量
Block語(yǔ)法。
Block類(lèi)型變量。
Block的用途。
- 作為函數(shù)參數(shù)
- 反向傳值
- 循環(huán)引用
11.blcok和其他傳值最明顯的特點(diǎn)就是可以逆向傳值,block可以進(jìn)行多條數(shù)據(jù)同時(shí)傳遞這方便了很多程序員但是必須參數(shù)類(lèi)型和傳遞類(lèi)型一致的情況下才可以進(jìn)行多條數(shù)據(jù)同時(shí)傳遞,Block 變數(shù)儲(chǔ)存的是一個(gè)block的參考,我們使用類(lèi)似宣告指標(biāo)的方式來(lái)宣告,不同的是這時(shí)block變數(shù)指到的地方是一個(gè)函數(shù),而指標(biāo)使用的是「*」,block則是使用「^」來(lái)宣告,我們可以定義一個(gè)全域的block