I need to extract a NSData item from within a block of a dispatch_sync().
Specifically, I can't do a 'return data' in mid block due to a compiler error:
Incompatible block pointer types passing 'NSData *(^)(void)' to parameter of type 'dispatch_block_t' (aka 'void (^)(void)')
The error occurs here:
if (data)return data; // data is present in memory cache
- (NSData *)dataForFile:(NSString *)fileName {
__block NSData *data;
// ... having problem with 'data' var within dispatch_sync
dispatch_sync(serialQueue, ^{
data = [_memoryCache objectForKey:fileName];
if (data)return data; // data is present in memory cache
NSString *archivePath = [_cacheDirectory stringByAppendingPathComponent:fileName];
data = [NSData dataWithContentsOfFile:archivePath];
if (data) {
[self cacheData:data toFile:fileName]; // put the recently accessed data to memory cache
}
});
return data;
}
...should I put a return type vs a (void) on the block? Or need it be re-engineered? One solution is to replace the dispatch with a @synchronized().
Question: is it possible to break out of a block & return during a dispatch_sync()?
Ask yourself where the return value would go. You've got no <var> = dispatch_sync(...)
, so you don't expect a result, which is good as dispatch_sync
doesn't return one!
dispatch_sync
takes a block with return type of void
- your block cannot return a value with return
. However a block can assign to captured local variables which have the __block
attribute - just as your data
variable does, and you do assign to that within your block. You don't need to assign to data
and return it, which seems to be what you are trying to do.
At a guess what you want is:
dispatch_sync(serialQueue, ^{
data = [_memoryCache objectForKey:fileName];
if (!data) // data is NOT present in memory cache
{
NSString *archivePath = [_cacheDirectory stringByAppendingPathComponent:fileName];
data = [NSData dataWithContentsOfFile:archivePath];
if (data) {
[self cacheData:data toFile:fileName]; // put the recently accessed data to memory cache
}
}
});
HTH