Reputation: 4100
I am using this code to return an image:
- (UIImage *)loadThumbnailForImageForUser:(int)userID inFolder:(int)folderNumber withFileName:(NSString *)fileName ofSize:(NSString *)size{
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"IMAGE%@%d", fileName, folderNumber]];
[DropBlocks loadThumbnail:@"" ofSize:@"s" intoPath:filePath completionBlock:^(DBMetadata* metadata, NSError* error){
}];
UIImage *img = [UIImage imageWithContentsOfFile:filePath];
return img;
}
The image returned is always nil. This is because the completionBlock is called later. Is there anyway to solve the issue and return the image?
Upvotes: 0
Views: 779
Reputation: 32066
The way I usually handle this problem is to use a delegate pattern:
@protocol ImageLoadingProtocol <NSObject>
@required
-(void) imageLoaded:(UIImage*) image;
@end
In your image loader header:
__weak id<ImageLoadingProtocol> delegate;
-(void) initWithDelegate:(id<ImageLoadingProtocol>) delegate;
//or
@property (nonatomic, weak) id<ImageLoadingProtocol> delegate
In your block:
[DropBlocks loadThumbnail:@"" ofSize:@"s" intoPath:filePath completionBlock:^(DBMetadata* metadata, NSError* error){
UIImage *img = [UIImage imageWithContentsOfFile:filePath];
[_delegate imageLoaded:img];
}];
And in the class that creates your image loader:
imageLoader = [[ImageLoader alloc] initWithDelegate:self];
//or
//imageLoader.delegate = self;
Then when the block is finished your class will receive a message imageLoaded:
and you should implement a method to handle it:
-(void) imageLoaded:(UIImage*) image
{
//Here is where your image is usable.
}
Here's another solution using blocks:
- (UIImage *)loadThumbnailForImageForUser:(int)userID inFolder:(int)folderNumber withFileName:
-(NSString *)fileName ofSize:(NSString *)size completionBlock:(void( ^ )( UIImage* image )) completionBlock
{
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"IMAGE%@%d", fileName, folderNumber]];
[DropBlocks loadThumbnail:@"" ofSize:@"s" intoPath:filePath completionBlock:^(DBMetadata* metadata, NSError* error)
{
UIImage *img = [UIImage imageWithContentsOfFile:filePath];
completionBlock(image);
}];
}
Caveat: Watch out for syntax issues and memory management issues, I didn't write this in an IDE
Upvotes: 2
Reputation: 119031
No, you can't use a return and an asynchronous block. Either ensure the image is available before calling or, and this is the preferred option, add a completion block to the method and call that, supplying the image as a parameter. Then you can call the block either immediately if the image is already available or later when it is made available by the inner block.
Upvotes: 0