Reputation: 37504
I have my instance variable declaration:
@interface TimelineTableViewController ()
@property (strong, nonatomic) NSMutableArray *avatars;
@end
And then my block:
void UIImageFromURL(NSURL *URL, NSString *key, void(^imageBlock)(UIImage *image), void(^errorBlock)(void)) {
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSData *data = [[NSData alloc] initWithContentsOfURL:URL];
UIImage *image = [[UIImage alloc] initWithData:data];
dispatch_async( dispatch_get_main_queue(), ^(void){
if (image != nil) {
[self.avatars setObject:image forKey:key];
NSLog(@"%@", self.avatars);
imageBlock( image );
} else {
errorBlock();
}
});
});
}
What I'm trying to do, is cache the downloaded image to an instance array to avoid re-downloading every the TableCell get's recreated. However, I get the error:
Use of undeclared identifier 'self'
I call my block like so, if that helps:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TweetCell *cell = (TweetCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSDictionary *tweetObject = _tweets[indexPath.row];
NSDictionary *userObject = tweetObject[@"user"];
NSString *avatarURL = userObject[@"profile_image_url"];
avatarURL = [avatarURL stringByReplacingOccurrencesOfString:@"_normal"
withString:@""];
NSURL *imageURL = [NSURL URLWithString:avatarURL];
UIImageFromURL(imageURL, avatarURL, ^(UIImage *image) {
[cell.avatarImage setImage:image];
}, ^{
NSLog(@"Failed to fetch profile picture.");
});
return cell;
}
Upvotes: 2
Views: 1494
Reputation: 540075
You can make UIImageFromURL()
an instance method instead of a plain C function,
then it has access to self
:
- (void)fetchImageFromURL:(NSURL *)URL key:(NSString *)key imageBlock:(void(^)(UIImage *image))imageBlock errorBlock:(void (^)(void))errorBlock
{
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSData *data = [[NSData alloc] initWithContentsOfURL:URL];
UIImage *image = [[UIImage alloc] initWithData:data];
dispatch_async( dispatch_get_main_queue(), ^(void){
if (image != nil) {
[self.avatars setObject:image forKey:key];
NSLog(@"%@", self.avatars);
imageBlock( image );
} else {
errorBlock();
}
});
});
}
and then call it like
[self fetchImageFromURL:imageURL key:avatarURL imageBlock:^(UIImage *image) {
[cell.avatarImage setImage:image];
} errorBlock:^{
NSLog(@"Failed to fetch profile picture.");
}];
Upvotes: 1
Reputation: 52632
Your code is not a method, but a straightforward C function. Therefore, there is no "self". Class methods start with "+", instance methods start with "-".
Upvotes: 1
Reputation: 8247
Before your block, use this line of code to modify your self
:
// Weak self
__weak MyViewController *weakSelf = self;
And call your variable like this :
void UIImageFromURL(NSURL *URL, NSString *key, void(^imageBlock)(UIImage *image), void(^errorBlock)(void)) {
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSData *data = [[NSData alloc] initWithContentsOfURL:URL];
UIImage *image = [[UIImage alloc] initWithData:data];
dispatch_async( dispatch_get_main_queue(), ^(void){
if (image != nil) {
[weakSelf.avatars setObject:image forKey:key];
NSLog(@"%@", weakSelf.avatars);
imageBlock( image );
} else {
errorBlock();
}
});
});
}
You can refer here for a powerfull answer about block
!
Upvotes: 2