Closed
Description
比如OC代码:
@implementation NetAPIClient
- (void)requestInfoWithObj:(NSMutableDictionary*)dictParameters andBlock:(void (^)(id data, NSError *error))block{
[[NetAPIClient sharedJsonClient] requestJsonDataWithPath:@"index.php" withParams:dictParameters withMethodType:Get andBlock:^(id data, NSError *error) {
if (data) {
block(data, nil);
}
}];
}
@end
使用JSPatchConvertor转换大概是下面的形式:
require('NetAPIClient');
defineClass('NetAPIClient', {
requestInfoWithObj_andBlock: function(dictParameters, blockCallback) {
NetAPIClient.sharedJsonClient().requestJsonDataWithPath_withParams_withMethodType_andBlock("index.php()", dictParameters, 1, block('id,NSError*', function(data, error) {
blockCallback(data, null);
}
}));
},
});
blockCallback这个地方的定义肯定是有问题的,Xcode运行直接crash,报错:TypeError: blockCallback is not a function. (In 'blockCallback(data, null)', 'blockCallback' is an instance of Object)
Wiki里提供的好像都是调用Block的示例,对于一个方法中带block参数的,如何进行定义与调用,应该没有,求指点
Activity
bang590 commentedon Nov 26, 2015
是在OC调
-requestInfoWithObj:andBlock:
这个方法吗?贴上来看看wonderffee commentedon Nov 26, 2015
requestInfoWithObj这个方法也是在JS里面调用的,代码我简化了许多
wonderffee commentedon Nov 27, 2015
来个更简单的例子,
这里面的两个函数并不一定在同一个类的。把上面的代码翻译为JS代码,大概是:
然后在js里调用runBlock,即self.runBlock(); 运行就Crash报错:msg: '[object Object]' is not a function (evaluating 'blk("test block")'),错误跟这个issue几乎一样:#122
但是我并不是十分明白它的解决方法
我想的是作为callBlock的block参数blk应该不是这样简简单单定义吧,到底应该怎么定义才能让上面的js代码正常运行起来呢?
bang590 commentedon Nov 28, 2015
这个定义跟用法都没有错,单纯把 block 传给 OC 调用或 OC 传给 JS 调用都是没问题的, 但目前不支持 JS 封装的 block 传到 OC 再传回 JS 去调用。
原因是:在 JS 用
block()
封装传到 OC 时,根据 这里的代码 生成的 block 参数类型是 void*,这个 block 再传回 JS 时 JavaScriptCore 不认带这种参数类型的 block,所以无法调用。简单模拟 block 不同参数类型传到 JS 的效果:
未找到解决方法 :(
wonderffee commentedon Nov 29, 2015
我感觉上面的代码的主要问题是JS不知道blk的实际类型,因为不知道所以就像你说的用void*类型代替,然后JS认为它是一个普通对象,而非block对象(function)。而它对应的OC代码是从参数就知道是什么类型的。
我想同样的问题应该是存在于OC的。如果把该函数对应的OC方法定义从- (void)callBlock:(void(^)(NSString str))blk修改为- (void)callBlock:(void)blk,函数体内的blk(@"test block");编译就会报错,因为认为它是对象,not a function。
但是在OC内,如果把blk强制转换成block形式,就没问题了,代码如下:
如果这个道理没错的话,我觉得要解决上面的问题,关键在于如何在js中对blk进行强制类型转换
bang590 commentedon Nov 30, 2015
你没理解我之前的解释,也没理解真正的原因。JS 知道 blk 的类型就是 block,JavaScriptCore 会自动把 block 转为 JS Function,这里没法转是因为这里传过来的 block 里的参数类型含有
void*
(!!!注意是block里的参数类型,不是 block 本身!!!),JavaScriptCore 不认这种参数类型,没法把它转为 JS Function。至于为什么这里 block 的参数类型会是void*
上一篇已经给出源码链接。wonderffee commentedon Nov 30, 2015
知道你的意思了,可是我单步调试了一下,genCallbackBlock这个函数好像根本没有调用到啊
CodeLife2012 commentedon May 19, 2016
@bang590 为什么需要声明为
void *
呢?liuyanhongwl commentedon Aug 22, 2016
如果block不加参数可以解决吗?
还是block有什么隐藏参数也加成了void * 类型吗?
@bang590
JeryCG commentedon Feb 15, 2017
@bang590 你好, 测试了下文档中代码
发觉加了require('JPEngine').addExtensions(['JPBlock']);
文档中的代码依旧会crash
msg: blk is not a function. (In 'blk("test block")', 'blk' is an instance of Object)
leixiang1986 commentedon Dec 8, 2022
这就是为什么现在的版本不支持masonry的原因吗?用masonry报:TypeError: undefined is not an object (evaluating 'make.__c')。
很早以前的版本是支持的,最新的版本不支持了,调试了,没找到原因。