当块从 swift 转移到 objective-c 时出现内存问题
Memory issue with block, when it is transferred from swift to objective-c
也许有人会想到解决一个有趣的问题。有一个obj-c方法,我重写为Swift:
https://pp.userapi.com/c846018/v846018818/1a0713/zsa8UZFcnfY.jpg
+ (instancetype)postUdpateTechnicianPhotoRequest:(UIImage*)image;
{
....
SCRequest* requset =
[IFTRequest requestWithURL:requestUrl
httpMethod:HTTPMethodPOST
parameters:nil
headers:@{ @"Content-Type" : [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] }];
[requset.updateRequestBlocksArray addObject:^(SCRequest *req) {
[req setDataToHTTPBody:body];
}];
requset.hudTitle = NSLocalizedString(@"Uploading photo...", @"");
requset.failureBlock = [requset defaultFailure];
return requset;
}
得到这个Swift方法,这很可能是问题所在:
let request = IFTRequest(url: requestUrl, httpMethod: .POST, parameters: nil, headers: ["Content-Type": "multipart/form-data; boundary=\(boundary)"])
let updateBlock: UpdateRequestBlock = {
[=13=]?.setDataToHTTPBody(body)
}
request?.updateRequestBlocksArray.add(updateBlock)
逻辑很简单,我们向数组添加一个包含数据的块,然后在obj-c中调用这个块class。该块是 typedef:
typedef void (^UpdateRequestBlock) (SCRequest* request);
问题是根据结果这个block内存不足,整体为NULL
Swift 和 ObjC 之间的 NSMutableArray 有问题。变量的捕获方式不同,稍后可能会出现数组内对象的问题。通过将 NSMutableArray 替换为 NSArray 解决了问题。
问题是 Objective-C 块和 Swift 函数是不同类型的东西。如果 Swift 发现您正在将 Swift 闭包传递给采用 Objective-C 块类型的 Objective-C 函数参数,它会将 Swift 闭包转换为Objective-C 块,所以它会起作用。但是在这里你将它传递给 NSMutableArray
的方法 -addObject:
,它接受一个类型为 id
的参数,它是一个通用的(非特定于块的)Objective-C 对象类型.在这种情况下,它不需要转换为 Objective-C 块,因为 Swift 闭包可以传递给 Objective-C 并直接用作 Objective-C 对象。但是这个可以在Objective-C中使用的Objective-C对象不是Objective-C块,你不能像块一样在Objective-C中使用。它只是一个包裹 Swift 值的不透明对象。
我相信如果你想在将它传递给 -addObject:
时强制它转换为 Objective-C 块,你可以这样做(我还没有测试过):
request?.updateRequestBlocksArray.addObject(myBlock as @convention(block) SCRequest -> Void)
也许有人会想到解决一个有趣的问题。有一个obj-c方法,我重写为Swift: https://pp.userapi.com/c846018/v846018818/1a0713/zsa8UZFcnfY.jpg
+ (instancetype)postUdpateTechnicianPhotoRequest:(UIImage*)image;
{
....
SCRequest* requset =
[IFTRequest requestWithURL:requestUrl
httpMethod:HTTPMethodPOST
parameters:nil
headers:@{ @"Content-Type" : [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] }];
[requset.updateRequestBlocksArray addObject:^(SCRequest *req) {
[req setDataToHTTPBody:body];
}];
requset.hudTitle = NSLocalizedString(@"Uploading photo...", @"");
requset.failureBlock = [requset defaultFailure];
return requset;
}
得到这个Swift方法,这很可能是问题所在:
let request = IFTRequest(url: requestUrl, httpMethod: .POST, parameters: nil, headers: ["Content-Type": "multipart/form-data; boundary=\(boundary)"])
let updateBlock: UpdateRequestBlock = {
[=13=]?.setDataToHTTPBody(body)
}
request?.updateRequestBlocksArray.add(updateBlock)
逻辑很简单,我们向数组添加一个包含数据的块,然后在obj-c中调用这个块class。该块是 typedef:
typedef void (^UpdateRequestBlock) (SCRequest* request);
问题是根据结果这个block内存不足,整体为NULL
Swift 和 ObjC 之间的 NSMutableArray 有问题。变量的捕获方式不同,稍后可能会出现数组内对象的问题。通过将 NSMutableArray 替换为 NSArray 解决了问题。
问题是 Objective-C 块和 Swift 函数是不同类型的东西。如果 Swift 发现您正在将 Swift 闭包传递给采用 Objective-C 块类型的 Objective-C 函数参数,它会将 Swift 闭包转换为Objective-C 块,所以它会起作用。但是在这里你将它传递给 NSMutableArray
的方法 -addObject:
,它接受一个类型为 id
的参数,它是一个通用的(非特定于块的)Objective-C 对象类型.在这种情况下,它不需要转换为 Objective-C 块,因为 Swift 闭包可以传递给 Objective-C 并直接用作 Objective-C 对象。但是这个可以在Objective-C中使用的Objective-C对象不是Objective-C块,你不能像块一样在Objective-C中使用。它只是一个包裹 Swift 值的不透明对象。
我相信如果你想在将它传递给 -addObject:
时强制它转换为 Objective-C 块,你可以这样做(我还没有测试过):
request?.updateRequestBlocksArray.addObject(myBlock as @convention(block) SCRequest -> Void)