手动创建block,签名丢失问题记录

410 阅读1分钟

手动创建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;
}