[IOS]如何使用block来实现回调
一.回调方法总结:
可以参考:https://www.jianshu.com/p/3ff91ef196d1
常用有三种:1.Delegate 和 DataSource 2.Notification 3.Blocks
二.Block
这里重点介绍Block这种用法:
在OC里面是Block,在swift里面叫closure,用法是类似的.
首先OC block简单参考如下:
https://www.jianshu.com/p/7d32ed28292f
这里面实现的是A跳转到B,B处理完,回调数据到A
但是这里面操作的时候有思维上的坑,首先是报野指针的错,然后通过判断是否为空发现,B中的block一直是空的,但是搞不懂为甚是空的.
然后我换了种方法,既然B那里是空的,那我就在A那里传一个block过去,操作如下:
参考:https://www.cnblogs.com/XYQ-208910/p/6257268.html
B.h:
@interface PingInfo : NSObject - (void) addCallBack:(void(^)(NSString *)) callBackBlock ;
B.m:
typedef void(^CallBackBlock) (NSString *); @interface PingInfo() @end @implementation PingInfo{ CallBackBlock _callBackBlock; } - (void) addCallBack:(void(^)(NSString *)) callBackBlock { _callBackBlock = callBackBlock; if(_callBackBlock){ _callBackBlock(@"test-=-=-=-=-="); } }
A.swift:
let pingInfo = PingInfo.init() pingInfo.addCallBack( { string in print("callback message: \(string)") } )
Perfect,没有任何问题.可以获得返回数据了.然后我就疑惑,是不是
pingInfo.callBackBlock = { string in print("callback message: \(string)") }
这行代码OC不会识别呢,是不是swift和OC之间的处理问题呢,然后我又换了纯swift来试一次回调,参考操作如下:
https://www.jianshu.com/p/20407ee99346
发现B.swift的block还是空的.然后我对照了一下我的代码:
A.swift
pingInfo.passBlock() //错误 pingInfo.callBackBlock = { string in print("callback message: \(string)") }
B.m:
- (void)passBlock{ if(_callBackBlock == NULL){ NSLog(@"callBackBlock null "); } if(_callBackBlock){ _callBackBlock(@"test-=-=-=-=-="); } }
终于发现了我犯了一个愚蠢的错误.因为网上的参考代码并没有调用B中的方法来实现回调,而是直接跳转处理后回调,一般想法都认为block在B中声明,那么应该是在B中赋值的.其实问题就出现在这里,block应该是在A中赋值的,B中调用的,流程如下:
OC(B)类里面声明--->swift controller(A)里面赋值----->OC类(B)里面调用------>swift controller(A)获得返回值
因此,我之前的做法直接使用了B类中的block调用,当然是空的,因为并没有执行赋值:
pingInfo.callBackBlock = { string in print("callback message: \(string)") }
所以正确的是:
pingInfo.callBackBlock = { string in print("callback message: \(string)") } pingInfo.passBlock() //正确
一般思维惯性都是同一个类里面声明和赋值,但是block好特别,同一个类里面只是声明和调用,打一个比喻,好像买基金,基金的种类和涨跌就是block的声明和调用,但是如果你不买,就是不对一个block赋值(买多少,才知道有多少份额),这只基金是和你无关的,同理,基金涨跌了,对你来说是异步的,结果根据你的赋值(份额)回调(显示)给你就是了.
综上,block有两种操作方式,要不就通过方法来传给B来使用,要不就直接赋值,其实本质都是一样的,和上面的基金例子一样,是否通过代理来买而已.