--------------------sunkaikees@gmail.com-------------------

block第一步

对于block之前想多了,从理解方向上出现问题,一直以为是个坎,闲来无事研究半天,感觉有点思路。虽然通了些,但对于深层次理解及灵活运用必然不到位,所以暂定block第一步。并且block多种语法也记不住,写此笔记,便于日后查看。

文章结构网络借鉴,block的几种用法。

(1).本地变量

     int (^sumBlock)(int ,int) = ^(int a,int b){   return  a+b;  }

(2).成员属性

   @property(nonatomic,copy) void(^wwBlock)(NSString *);

(3).方法参数

    -(void)returntextWith:(void(^)(NSString *dd))ssblock;

(4).typedefin

    typedef int (^sumBlock)(int a,int b);

   sumBlock myblock = ^int (int a,int b){  }

**typedefin 只是讲block起别名,定义成sumblock、block属性用copy**

(1).用作本地变量

NSString* (^nameBlock)(NSString *,NSString *) = ^(NSString *first,NSString *last){

NSString  *name = [NSString stringWithFormat:@"%@ %@",first,last];

return name;

};

NSLog(@"%@",nameBlock(@"zhao",@"si"));

本地变量与     int  a  = 7;一样

* block可以访问局部变量,但是不能修改,否则会编译报错.

如果要在block内部修改局部变量,则需要使用__block来修饰该局部变量,如下,

__block NSString *lastName = @"wang";

* 当我们无法理解block如何产生各种回调时以及原理时,不妨冷静头脑看一下block最基本的用法:

block名言: ** * 要想执行block大括号内部的代码(即回调代码),只要在你想的地方敲出block名字,填要传的参数即可,大括号内的回调代码就可以用这些参数处理问题***

如上文我们想知道@"zhao"与@"si"的组合名字是什么,我们在某处调用block并填写参数:nameBlock(@"zhao",@"si"),括号内执行:NSString *name = [NSString stringWithFormat:@"%@ %@",first,last];

至此 貌似block的功能也可以用函数或一个返回合并后的字符串解决,但细想,block可以传多个参数(个人认为block的最大优势,暂时的理解)。
(2).用作成员属性

声名方法:@property(notomic ,copy)void (^myBlock)(NSString *);

block 用作本地变量的经典作用就是界面B对界面A的值得回传。

栗子:有界面A和界面B,在界面B中取得的值,需要回传到界面A。

思维分析:A界面要想拿到B界面的值,以block思维,必然是A有block代码块,B在想调用的时候调用并传参,A得到参数(即B穿给A的值)。

实现方法:

1.在B控制器定义一个block属性

@property(nonatomic,copy) void(^wwBlock)(NSString *);

2.在B.h中声名一个带有Block的方法,写法如下:

声名:

-(void)returntextWith:(void(^)(NSString *dd))ssblock;

这个方法是为了在跳转到B界面时把A中的block传给B,并且B保存到step 1中定义的属性。(稍有点绕,作用且看)

实现:

-(void)returntextWith:(void(^)(NSString *dd))ssblock{

self.wwBlock = ssblock;

}

3.B界面调用自己的block,也就是A传来的Block,保存在属性中,指针地址相同。

-(void)btClink{

if (self.wwBlock != nil) {

    self.wwBlock(@"你好");

}

[self.navigationController popViewControllerAnimated:YES];

}

点击按钮,调用wwBlock,将B中的“你好”,作为参数。这个block的代码块在A界面,所以block会去A界面执行回调。

0.A界面代码

B_ViewController *Bvc = [[B_ViewController alloc]init];

[Bvc returntextWith:^(NSString *dd) { NSLog(@"%@",dd); }];

 [self.navigationController pushViewController:VC animated:YES];

A 界面在push到B界面时,调用B界面的return方法,将NSLog回调代码块作为方法参数传给B,(B保存到属性),当B调用block时,执行代码块,打印dd (传来的值)。

?(一直纠结打印应该再B界面而非A界面,但运行代码发现确实回到A界面调用Log,或许是因为block是在A界面定义的,B界面只是得到了同一指针,结合block用作函数参数又感觉想多了,就是先后问题)

*熟练使用时,应先写A的代码,但暂时还是先写B,再写A。

*return方法:block作为函数参数是下段内容
(3).用作方法参数

当我们一根筋的理解好“block名言”时,block作为函数参数也就不必费事了。这个block就是函数的参数而已,只不过写法奇怪。而什么时候调用,或者是否调用,完全由我们控制。基本做法是,先执行方法,在方法中调用block,调用函数的地方会执行block。

Manger控制器中处理名字的方法,带有block参数,Manger.h代码:

-(void)mergeNamebByFisrt:(NSString *)firstName last:(NSString *)lastName responBlock:(void(^)(bool response,NSString *Name,NSInteger nameLength))myBlock;

Manger.m代码:

-(void)mergeNamebByFisrt:(NSString *)firstName last:(NSString *)lastName responBlock:(void(^)(bool response,NSString *Name,NSInteger nameLength))myBlock{

//处理方法内部任务

NSString *name = [NSString stringWithFormat:@"%@%@",firstName,lastName];

bool isContain = [name containsString:@"三"];

NSInteger namelen = name.length;

//调用block,根据此方法的处理结果,返回参数。

myBlock(isContain,name,namelen);

}

在控制器XX中调用此方法:

[MangerVC mergeNamebByFisrt:@"张" last:@"三" responBlock:^(bool response, NSString *Name, NSInteger nameLength) {

    NSLog(@"名字是:%@   名字占几个字符:%ld",Name,(long)nameLength);

    if (response) {

        NSLog(@" 名字包含“三”字 ");

    }

}];

可以看到,程序调用方法时与以前一样,执行方法内部逻辑,只是执行完成后,我们可以调用block,这时XX控制器中调用时的block回调Log方法才会执行。

所以这种作为参数的block常常用于多线程处理网络请求,处理完成后block产生回调,更新UI或MBProgress "-处理完成-";
(4).用typedef 重新定义block格式

这只是用typedef 重新定义block而已,算是一个小技巧吧。

typedef int (^sumBlock)(int a,int b);

a. @property(notomic,copy)sumBlock ssblock;

b. sumBlock yyblock = ^int (int a,int b){return a+b;} ;

 。。。。。
posted @ 2019-01-17 19:29  雪天微风吹  阅读(125)  评论(0编辑  收藏  举报