iOS开发block

一、基本概念:

Block是一种C语言的数据类型,指向结构体的指针,平常我们将Block当作一个代码段使用,相当于函数,Block相比于函数的优点是 Block可以当做一个参数传递而函数/方法不能.。我们可以用Block写一些函数语句,可以使用多线程。Block也可以作为一个回调,不仅包含回调期间的代码,也包含了执行期间需要的数据。类似于"闭包",闭包的定义是可以从函数外部访问函数内部的变量。

二、基本用法:

1)无参无返回值(最简单形式)

定义格式:void (^block名)() = ^{代码块;};

使用格式:block名();

2)无参有返回值(以返回值为int为例)

定义格式:int (^block名)() = ^{代码块;};

使用格式:int result = block名();

3)有参无返回值(以参数为int为例)

定义格式:void (^block名)(int) = ^(int a){代码块;};

使用格式:  block名(6);

4)有参有返回值(以参数、返回值为int为例;可以有多个参数)

定义格式:int (^block名)(int) = ^(int a){代码块;};

使用格式:int result = block名(6);

5)利用typedef定义block类型(和指向函数的指针很像)

定义格式:typedef 返回值类型(^新别名)(参数类型列表);

例:typedef int (^myBlock)(int,int);

三、Block访问外部变量

1)在block内部可以访问block外部的变量,但是,这是一个新的内存空间变量;

block内部也可以定义和block外部同名的变量,此时这个局部变量会屏蔽外部变量的作用域。

2)如果想要在block内部修改外部的局部变量,需要给该变量加上__block关键字;原因是加__block,block会引用常量变量的地址,则可以任意修改该变量指向的内容。如果不加__block直接在block内部修改变量,会编译报错,block内部变量是只读的。

四、Block使用技巧和注意事项

1)block的快速提示,输入inlineBlock 会有代码提示;

2)block变量用作方法的参数时,最好把参数类型列表部分加上具体的参数名

3)利用block遍历取值

例: [dict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {

}];

5)  block修饰:block的发展也经过了MRC和ARC两个阶段;

MRC情况下:用copy修饰后,如果要在block内部使用对象,则需要进行__block typeof(Target) blockTarget = Target处理,在block里面用blockTarget 操作。

ARC情况下:如果用copy修饰,该block就会存储在堆空间以避免在使用时发生释放。但会对block的内部对象进行强引用,导致循环引用,内存无法释放。 所以block使用 self ,要使用 self 弱引用写法. 即__weak typeof(self) weakSelf = self;如果用weak修饰block,该block就会存放在栈空间,虽不会出现循环引用,但容易造成需要使用对象时,对象已经不存在的问题,原因是存储在栈空间的各种数据是系统自动处理的,并不需要程序猿手动处理,所以我们也不知道对象什么时候会被释放。

6)循环引用

分析循环(VC代表viewController控制器)

已知 : op --> self(VC) 强引用

如果 self 强引用的对象,对 op 也有强用.那么就会有循环引用

self(VC) --> queue/OPCache --> op --> self(VC)

所以block使用 self ,要使用 self 弱引用写法. 即__weak typeof(self) weakSelf = self;

GCD中的block(任务)出现self,会造成循环引用吗?  ----- GCD中的block可以直接使用 self

block循环引用的条件: block------->强应用(self)  self ------->强引用(block属性)

NSOperation 中的blcok中是否可以出现 self ?

一般情况下 NSOperationQueue 需要作为一个属性. 将操作添加到操作队列中!

注意: 1.确实会出现循环引用!

但是: 操作一旦执行完毕之后,就会被自动销毁! 所以 NSOperation 中可以出现 self.

7)block可以在两个对象之间进行传值,类似于代理和通知;

以POST请求为例,假如我在A对象中封装了POST请求的方法,该方法请求回来的数据想传递给B对象,就可以利用block实现:

代码示例:

"A对象中声明方法

//MARK:- 一句话封装POST请求

- (void)POSTRequestWithURLString:(NSString *)urlString andDict:(NSDictionary *)pramarts andSuccessBlock:(successBlock)successblock andFalseBlock:(falseBlock)falseblock ;

"实现方法

- (void)POSTRequestWithURLString:(NSString *)urlString andDict:(NSDictionary *)pramarts andSuccessBlock:(successBlock)successblock andFalseBlock:(falseBlock)falseblock {

//MARK:- 创建请求

NSURL *url = [NSURL URLWithString:urlString];

#warning - POST请求要创建可变请求

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:15];

//MARK:- 设置请求体、请求方法等参数

request.HTTPMethod = @"POST";

NSMutableString *strM = [NSMutableString string];

[pramarts enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {

NSString *pramKey = key;

NSString *pramValue = obj;

[strM appendFormat:@"%@=%@&",pramKey,pramValue];

}];

NSString *pramart = [strM substringToIndex:strM.length-1];

request.HTTPBody = [pramart dataUsingEncoding:NSUTF8StringEncoding];

//MARK:- 发送请求

[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

if (data&&!error) {

if (successblock!=nil) {//一定要先判断block是否为空

successblock( obj,response);//回调

}

}else{

if (falseblock!=nil) {//同上

falseblock(error);

}

}

}]resume];

}

"B对象调用方法

[[YQPOSTRequest sharedPOSTRequest] POSTRequestWithURLString:urlStr andDict:pram andSuccessBlock:^(NSData *data, NSURLResponse *response) {

NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);

} andFalseBlock:^(NSError *error) {

NSLog(@"%@",error);

}];

五、解决OC中block循环引用的三种方式

1)解决循环引用的第一种方式

//iOS 5.0 引用来解决循环引用的方式  和weak属性关键字作用类似

//当对象被系统回收时  对象的地址 会自动指向 nil  不会出现野指针访问

__weak typeof(self) weakSelf = self;

2)解决循环引用的第二种方式

//    __weak typeof(self) weakSelf = self;

//会引起 EXC_BAD_ACCESS 错误 是MRC 时代最常见的错误  野指针  --> 坏地址访问

// 和 assgin属性关键字的作用类似  对象被系统回收时 对象的地址不会自动指向nil

// iOS4.0 和block 一起推出的 用来解决循环引用的

__unsafe_unretained typeof(self) weakSelf = self;

3) 解决循环引用的第三种方式

//weak-strong-dance wwdc 推出的解决方式  在AFN中被大量的运用到

__weak typeof(self) weakSelf = self;

[self.tools loadData:^(NSString *result) {

//闭包中对弱引用的weakSelf 在强引用一下

__strong typeof(weakSelf) strongSelf = weakSelf;

NSLog(@"%@ %@",result,strongSelf);

}];

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,875评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,569评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,475评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,459评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,537评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,563评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,580评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,326评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,773评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,086评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,252评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,921评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,566评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,190评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,435评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,129评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,125评论 2 352

推荐阅读更多精彩内容