Reputation: 701
Trying to load image asynchronously I'm getting this error "Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ valueForUndefinedKey:]: this class is not key value coding-compliant for the key img.'" My code is as below
NSString *str = "URL of an image";
NSMutableDictionary *record = [NSMutableDictionary dictionary];
[record setObject:str forKey:@"img"];
record = [_array objectAtIndex:indexPath.row];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
if ([record valueForKey:@"img"]) {
NSLog(@"in if");
cell.m_img.image = [record valueForKey:@"img"];
} else {
dispatch_async(queue, ^{
NSLog(@"in else");
NSURL *imageurl = [[NSURL alloc] initWithString:str];
NSData *image = [[NSData alloc] initWithContentsOfURL:imageurl];
dispatch_async(dispatch_get_main_queue(), ^{
[record setValue:[UIImage imageWithData:image] forKey:@"img"];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
});
});
}
Please advise where am I getting wrong here. Thanks Mayur
Upvotes: 0
Views: 1252
Reputation: 701
Solved The problem with the help of your comments and answer. What I did is created NSMutable Dictionary in Globally used class and initialised the variable. Thanks all for the help
arr = [[NSMutableDictionary alloc] init];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
if ([[[DataManager sharedInstance] arr] objectForKey:str]) {
NSLog(@"in if");
[cell m_img].image = [UIImage imageWithData:[[[DataManager sharedInstance] arr] objectForKey:str]];
} else {
dispatch_async(queue, ^{
NSLog(@"in else");
NSURL *imageurl = [[NSURL alloc] initWithString:str];
NSData *image = [[NSData alloc] initWithContentsOfURL:imageurl];
[[[DataManager sharedInstance] arr] setObject :image forKey:str];
[cell m_img].image = [UIImage imageWithData:[[[DataManager sharedInstance] arr] objectForKey:str]];
});
}
Upvotes: 0
Reputation: 14068
It is ost likeli this line
[record valueForKey:@"img"]
objectForKey:
will return nil in the event that the key img is not set. The better choice in your case.
However, please review your code in general. You start off by creating a new NSMutableDictionary
and assign it to record
. Then you add a string object to that dictionary. Fine so far.
After that you fetch an object from the array _array which you assign to record
too. By then you do not have any reference to the newly created dicitionary any more. Is that intended. If you do not ARC then you create a memory leak here.
Edit in response to a comment below:
NSMutableDictionary *record = [NSMutableDictionary dictionary]; // here you create a new empty instance of NSMutableDictionary and store it in record. It has a retain count of 1
[record setObject:str forKey:@"img"]; // here you add an object to that new dictionary. Now it has exactly one entry with the key "img"
record = [_array objectAtIndex:indexPath.row]; //and here you discard the retained newly creaded dictionary by assigning another one from the array _array. What is the purpose of that?
Upvotes: 0
Reputation: 1313
Check if object in array is of dictionary type
NSString *str = "URL of an image";
NSMutableDictionary *record = [NSMutableDictionary dictionary];
if([[_array objectAtIndex:indexPath.row]isKindOfClass:[NSDictionary class]])
record = [_array objectAtIndex:indexPath.row];
else
[record setObject:str forKey:@"img"];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
if ([record valueForKey:@"img"]) {
NSLog(@"in if");
cell.m_img.image = [record valueForKey:@"img"];
} else {
dispatch_async(queue, ^{
NSLog(@"in else");
NSURL *imageurl = [[NSURL alloc] initWithString:str];
NSData *image = [[NSData alloc] initWithContentsOfURL:imageurl];
dispatch_async(dispatch_get_main_queue(), ^{
[record setValue:[UIImage imageWithData:image] forKey:@"img"];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
});
});
}
Upvotes: 1
Reputation: 4705
Replace
[record valueForKey:@"img"]
with
[record objectForKey:@"img"]
Upvotes: 1