Block使用详解,Block与代理相比的优点与缺点

简介: Block使用详解,Block与代理相比的优点与缺点

Block是iOS4.0+ 和Mac OS X 10.6+ 引进的对C语言的扩展,用来实现匿名函数的特性。

Block是Apple Inc.为C、C++以及Objective-C添加的特性,使得这些语言可以用类lambda表达式的语法来创建闭包。

闭包就是能够读取其它函数内部变量的函数。就是在一段请求连续代码中可以看到调用参数(如发送请求)和响应结果。所以采用Block技术能够抽象出很多共用函数,提高了代码的可读性,可维护性,封装性。

不像代理声明了一个代理函数,在调用的类内部还要实现该函数,让人莫名惊诧,若一个页面能发送多个请求,并且用多点触控同时触发发送多个请求,那个这个页面的代理函数很难区分是那个请求的结果,胡乱解析消息很容易崩溃。有人说我发送一个请求就起个菊花,消息不返回,不让发其他请求。告诉你这个行不通,原因是弹出菊花是起一个线程,调用起线程很快会返回成功,但是你起的线程被加入主线程并且实际运行起来是需要时间的,大约需要130毫秒,并且那个提示菊花提示框也是刷新UI线程才出来的。所以当你两个手指同时点击两个发送请求或切换也页面的按钮时,在当点吉第一个按钮并起菊花,但是在菊花出现前的点击了另一个按钮时,那么你就连续发送了两个请求了。那么你用代理实现时就很难分出那个消息,只有你的响应消息中带有消息类型可能会分出来,若服务器做的不够强大,当出现异常时,找不发送请求,给你来个通用错误响应消息,你只有傻眼了。这样多个消息在一个函数里解析也不利于封装。

综上所述:Block就是把你发送的请求和响应放在一块,配成一对,所以又叫代码块嘛。

Block的优点是能把发起的部分和响应的部分放在一起,可以很容易的理解和处理。

缺点是若你的响应部分处理不当,若多次返回,那么你的代码会乱套;若你返回时返回错误返回了其它的代码块就会出现跑到其它流程里面去;最严重的是若代码永远不返回,那么你的程序又是根据返回结果跳转页面的,那么你永远停留在原页面,并且会造成内存不能释放,谁让你扮演红娘失败呢!

举个实际的例子,我发送下线请求,由于代码写的有问题,导致在长连接线程里返回的上线成功的BLOCK,结果导致程序走入上线流程里了(上线BLOCK处理部分)。

代理也有其优点和适用场景:代理在自定义控件方面具有其绝对的优势。如:你想定义一个显示无网络信息的标签和一个按钮,当你点击按钮时进行操作(切换检查的网络地址,IOS自带的网络检查是连接到苹果服务器域名。点击按钮时你可以检查你服务器的域名)域名来最终显示或隐藏这个图层,那么这个图层可以抽象成一个控件,这个控件的响应函数就用代理函数来实现。以前我的文章介绍的小气泡的控件实现方法也是用代理实现了。

适合代理实现的方法有一个显著的特点,只需要处理响应(如:按钮响应事件),没有或不考虑发起者。代理方法在自定义控件上大展宏图。

适合BLOCK的显著特点,有明确的发起方和响应方,两者能配对需要紧密联系。如:网络请求。

BLOCK最典型的是大所周知的AFNETWORK第三方库。它能解决发送函数找到自己对应的响应消息。代理方面的典型例子见我的文章《自己实现异步发送请求和图片》:http://blog.csdn.net/jia12216/article/details/47043935。


BLOC首先你在.h文件中声明BLOC对象,当然返回的参数你可以自己定义:

typedef void (^RequestCompletionBlocks)(NSDictionary *result,BOOL successed);

typedef void (^SocketLineSuccessBlocks)(BOOL successed);

typedef void (^SocketLineFailedBlocks)(BOOL successed);


@property (nonatomic,weak) RequestCompletionBlocks myblock; //block返回参数

@property (nonatomic,weak) SocketLineSuccessBlocks socktlineSuccessBlock; //成功连接

@property (nonatomic,weak) SocketLineFailedBlocks socktlineFailedBlock; //失败连接

注意:若你的block是在另一个子线程里返回,那么你不能用weak或assign,要用strong声明,不然走的是作死的路。当然你在通知里返回或在其它主线程里返回,你用weak,内存更安全。

如:

@property (nonatomic,strong)  RequestCompletionBlocks myblock; //block返回参数
@property (nonatomic,strong)  SocketLineSuccessBlocks socktlineSuccessBlock; //成功连接
@property (nonatomic,strong)  SocketLineFailedBlocks socktlineFailedBlock; //失败连接

-(void)socketConnectHost:(SocketLineSuccessBlocks)onSuccesscpmlention

failCompltion:(SocketLineFailedBlocks)onfailCompltion// socket连接


在.m文件中实现该函数就可以了

// socket连接

-(void)socketConnectHost:(SocketLineSuccessBlocks)onSuccesscpmlention

failCompltion:(SocketLineFailedBlocks)onfailCompltion// socket连接

{

//这个存储发送请求对象和响应请求对象到全局变量中

self.socktlineSuccessBlock = onSuccesscpmlention;

self.socktlineFailedBlock = onfailCompltion;

//这个是调用了另一个BLOCK函数

[[checkReachability sharedCheckReachability] checkReachability:^(NetworkStatus status) {

if (status == NotReachable)

{

//无网络返回失败

onfailCompltion(NO);

}

else

{

self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

        NSError *error = nil;

        [self.socket connectToHost:self.socketHost onPort:self.socketPort withTimeout:-1 error:&error];
        //请求响应的成功消息在另一个socket线程函数里返回
    }
}];

}

//请求响应的成功消息在socket线程函数里返回

pragma mark - 连接成功回调

(void)socket:(GCDAsyncSocket )sock didConnectToHost:(NSString )host port:(uint16_t)port

{

//后台也能用

// [self.socket performBlock:^{

// self.socket.enableBackgroundingOnSocket = YES;

// }];

NSLog(@”socket连接成功”);

STATUS = Socketonline;

self.socktlineSuccessBlock(YES);

self.readhead = YES;

[self.socket readDataToLength:10 withTimeout:-1 tag:1];

}

BLOCK函数的调用大家都知道吧:

// 服务器掉线,重连

[self socketConnectHost:^(BOOL successed) {

if(successed)

{

//服务返回成功时的处理

}

else

{

//服务器返回的处理失败的处理

}

        } failCompltion:^(BOOL successed) {
             //异常时的处理,通常指非服务器返回的异常

        }];
目录
相关文章
|
11月前
|
存储 编译器
深入解析i++和++i的区别及性能影响
在我们编写代码时,经常需要对变量进行自增操作。这种情况下,我们通常会用到两种常见的操作符:i++和++i。最近在阅读博客时,我偶然看到了有关i++和++i性能的讨论。之前我一直在使用它们,但从未从性能的角度考虑过,这让我突然产生了兴趣。尽管它们看起来相似,但它们之间存在微妙而重要的区别。在本文中,我们将详细解释i++和++i之间的区别,以及它们对代码性能的影响。
349 1
深入解析i++和++i的区别及性能影响
|
1月前
|
存储 NoSQL 关系型数据库
|
1月前
|
SQL Java API
使用 JPA 有哪些优点?
【8月更文挑战第21天】
58 0
|
2月前
|
缓存 算法
KV cache复用与投机采样问题之多轮对话复用KV cache对FTT变长问题如何解决
KV cache复用与投机采样问题之多轮对话复用KV cache对FTT变长问题如何解决
63 0
|
4月前
|
测试技术 数据处理 数据库
关于在 ABAP 中使用 PACKAGE SIZE 进行分块读写,块大小具体维护成多少比较合适?
关于在 ABAP 中使用 PACKAGE SIZE 进行分块读写,块大小具体维护成多少比较合适?
|
4月前
|
安全 Android开发
内存标记扩展:通过架构增强内存安全性
内存标记扩展:通过架构增强内存安全性
92 0
|
9月前
|
缓存 NoSQL 关系型数据库
缓存的设计方式
缓存的设计方式
|
芯片 Anolis
性能优化特性之:TLBI - TLB range优化
本文介绍了倚天实例上的内存优化特性:TLBi,并从优化原理、使用方法进行详细阐述。
|
缓存 自然语言处理 微服务
合理的使用缓存提升接口性能
合理的使用缓存提升接口性能
|
缓存 前端开发 大数据
如何设计一个缓存函数
在项目中你有优化过自己写过的代码吗?或者在你的项目中,你有用过哪些技巧优化你的代码,比如常用的函数防抖、节流,或者异步懒加载、惰性加载等。
112 0
如何设计一个缓存函数