手动创建block,在二次使用时,block签名丢失问题记录:
原因:
在二次使用生成过的block的时候,由于第一次创建的block中签名是通过[self.signature.types cStringUsingEncoding:NSASCIIStringEncoding]方法创建,而这个方法返回值可能被系统随时释放,所以二次调用block时,就会找不到方法签名而出错,
解决方案:
手动malloc个char *类型做签名,避免系统释放
- (void *)blockPtrWithCtx:(NSDictionary *)ctx
{
_ctx = ctx;
if (_generatedPtr) {
return _blockPtr;
}
_generatedPtr = YES;
ffi_type *returnType = [OCMethodSignature ffiTypeWithEncodingChar:[self.signature.returnType UTF8String]];
NSUInteger argumentCount = self.signature.argumentTypes.count;
_cifPtr = malloc(sizeof(ffi_cif));
void *blockImp = NULL;
_args = malloc(sizeof(ffi_type *) *argumentCount) ;
for (int i = 0; i < argumentCount; i++){
ffi_type* current_ffi_type = [OCMethodSignature ffiTypeWithEncodingChar:[self.signature.argumentTypes[i] UTF8String]];
_args[i] = current_ffi_type;
}
_closure = ffi_closure_alloc(sizeof(ffi_closure), (void **)&blockImp);
if(ffi_prep_cif(_cifPtr, FFI_DEFAULT_ABI, (unsigned int)argumentCount, returnType, _args) == FFI_OK) {
if (ffi_prep_closure_loc(_closure, _cifPtr, JPBlockInterpreter, (__bridge void*)self, blockImp) != FFI_OK) {
NSAssert(NO, @"generate block error");
}
}
char *char_signature = (char *)malloc(sizeof(unichar *)*self.signature.types.length);
for (int i = 0; i < self.signature.types.length ; i++) {
char_signature[i] = [self.signature.types characterAtIndex:i];
}
//栈中创建
struct JPSimulateBlockDescriptor descriptor = {
0,
sizeof(struct JPSimulateBlock),
(void (*)(void *dst, const void *src))copy_helper,
(void (*)(const void *src))dispose_helper,
char_signature
};
/ ** 错误代码
struct JPSimulateBlockDescriptor descriptor = {
0,
sizeof(struct JPSimulateBlock),
(void (*)(void *dst, const void *src))copy_helper,
(void (*)(const void *src))dispose_helper,
[self.signature.types cStringUsingEncoding:NSASCIIStringEncoding]
};
*/
//堆中创建 _descriptor = malloc(sizeof(struct JPSimulateBlockDescriptor));
//栈的内容拷贝到堆中 memcpy(_descriptor, &descriptor, sizeof(struct JPSimulateBlockDescriptor));
struct JPSimulateBlock simulateBlock = {
&_NSConcreteStackBlock,
(BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_SIGNATURE),
0,
blockImp,
_descriptor,
(__bridge void*)self
};
_blockPtr = Block_copy(&simulateBlock);
return _blockPtr;
}