Why is SDWebImage with UITableView causing exception? - iphone

I'm a noob to iphone development and I am trying to implement the SDWebImage library into my project. My project builds fine, however it when I display my tableview my app crashes with an invalid argument exception. I followed the installation instructions thoroughly. I added the ImageIO framework, added the -fobjc-arc flag since my project is non-ARC, and imported the appropriate header. Any help is greatly appreciated.
MY Exception
'NSInvalidArgumentException', reason: '-[UIImageView setImageWithURL:placeholderImage:]: unrecognized selector sent to instance 0x6e47d50'
My Code
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
//Lazy Loader
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"mylogo.png"]];
// Configure the cell...
NSDictionary *aTweet = [tweets objectAtIndex:[indexPath row]];
cell.textLabel.text = [aTweet objectForKey:#"text"];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.font = [UIFont systemFontOfSize:12];
cell.textLabel.minimumFontSize = 10;
cell.textLabel.numberOfLines = 4;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.detailTextLabel.text = [aTweet objectForKey:#"from_user"];
NSURL *url = [NSURL URLWithString:[aTweet objectForKey:#"profile_image_url"]];
NSData *data = [NSData dataWithContentsOfURL:url];
cell.imageView.image = [UIImage imageWithData:data];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}

Inside the top of that file, have you included the SDWebImage header, ie:
#import <SDWebImage/UIImageView+WebCache.h>
(if you are using cocoapods.. otherwise something like:)
#import "SDWebImage/UIImageView+WebCache.h"
or
#import "UIImageView+WebCache.h"
edit:
Why have you got this code at the top:
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"mylogo.png"]];
when you have this setting it again at the bottom:
NSURL *url = [NSURL URLWithString:[aTweet objectForKey:#"profile_image_url"]];
NSData *data = [NSData dataWithContentsOfURL:url];
cell.imageView.image = [UIImage imageWithData:data];
you dont need both - perhaps remove the code that is at the bottom that doesnt use the lazy loader?

Related

Set UITableview cell image from url in iOS

I am setting image on UITableViewCell using image url ,but the images doesn't get load unless i scrolls the UITableView.Here is the code that i have been using,i got to know about SDWeb Image library to download images from url,but i does;t want to use any library.Please tell me what aim doing wrong in this.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSDictionary *dictCard=[cardsDetailsArray objectAtIndex:indexPath.row];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:10];
UILabel *dateLabel = (UILabel *)[cell viewWithTag:11];
UIImageView *cellImage=(UIImageView *)[cell viewWithTag:0];
CGSize firstSize=CGSizeZero;
if([[dictCard objectForKey:#"orientation"]isEqualToString:#"1"]){
[cellImage setFrame:CGRectMake(0, 0, 75, 68)];
firstSize=CGSizeMake(75,68);
}
if([[dictCard objectForKey:#"orientation"]isEqualToString:#"0"]){
[cellImage setFrame:CGRectMake(0, 0, 107, 72)];
firstSize=CGSizeMake(107,72);
}
[cellImage setBackgroundColor:[UIColor clearColor]];
NSString *string=[dictCard objectForKey:#"email_sent"];
NSArray *items = [string componentsSeparatedByString:#","];
dateLabel.text=[dictCard objectForKey:#"date"];
nameLabel.text=[NSString stringWithFormat:#"Sent to %d People",[items count]];
NSURL* url = [NSURL URLWithString:(NSString *) [dictCard objectForKey:#"card_thumbnail"]];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
UIImage* image = [[UIImage alloc] initWithData:data];
//i am scaling the image here
UIImage *imageScale=[self imageWithImage:image scaledToSize:firstSize];
[cellImage setImage:imageScale];
}
}];
return cell;
}
I have also added [__tableViewDraft reloadData];after setting the cell image but due to this my cell keeps on changing its cell image.
Once the image has been downloaded, you need to ask iOS to refresh the cell. Check out reloadRowsAtIndexPaths:withRowAnimation:, among others.
Typically you might have have cells backed by CoreData objects and download and save the image to the managed object. You'd then have an NSFetchedResultsControllerDelegate trigger an update when the managed object changes, refreshing the row.

JSON Image Parsing/Prefixed URL

I have established successful parsing of text and images in a table view using JSON/PHP/MYSQL. I am only storing the location of the images in the database and the actual images are stored in a directory on my server. The only thing that is stored related to the image in the database is the name. Example car.jpg. What I want to do is prefix the URL of the image location on my server so they can be parsed without me having to go into the DB and manually entering the URL. Here is some of my code...
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"studentsCell";
StudentsCell *cell = (StudentsCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"StudentsCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSDictionary *studentsDict = [students objectAtIndex:indexPath.row];
//I want to prefix the URL for the key imagepath but i dont know where and how to do it.
NSURL *imageURL = [NSURL URLWithString:[studentsDict objectForKey:#"imagepath"]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *imageLoad = [[UIImage alloc] initWithData:imageData];
cell.imageView.image = imageLoad;
NSString *name = [NSString stringWithFormat:#"%# %#", [studentsDict valueForKey:#"first"], [studentsDict valueForKey:#"last"]];
cell.title.text = name;
NSString *subtitle = [NSString stringWithFormat:#"%#", [studentsDict objectForKey:#"email"]];
cell.subtitle.text = subtitle;
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(265, 6, 44, 44);
[button setImage:[UIImage imageNamed:#"email.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(email:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button];
// cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cellbackground.png"]];
return cell;
}
Let's assume you had something like:
NSURL *baseURL = [NSURL URLWithString:#"http://www.your.site.here/images"]; // whatever the folder with the images is
Then you could do:
NSURL *imageURL = [baseURL URLByAppendingPathComponent:[studentsDict objectForKey:#"imagepath"]];
By the way, you should consider using a UIImageView category, such as SDWebImage. Then, instead of loading a NSData with the image data synchronously, you can do an asynchronous image load:
[cell.imageView setImageWithURL:imageURL
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
The placeholder is what should be shown while the image is being loaded (perhaps just a blank image), and SDWebImage will then asynchronously retrieve the image and update the cell when it's retrieved. This will yield a far more responsive user interface. It will also avail yourself of image caching (so if you scroll down and then back up, the image won't be retrieved again).
AFNetworking has a similar UIImageView category, but not quite as robust of an implementation. But if you're already using AFNetworking, it's an option.

Fetching and displaying facebook profile picture in a UIImage

I'm trying to make a facebook friend picker displaying the friends who currently have the app installed that are also facebook friends with the current user.
Here I'm fetching the user's facebook profile picture but, I seem to have a warning where the last statement is not used. Thanks for your help.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"friendCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFUser *facebookID = [[PFUser alloc] init];
facebookID = [friendUsers objectAtIndex:0];
NSString *fbIdString = [[NSString alloc] init];
fbIdString = [facebookID objectForKey:#"fbId"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
NSURL *profilePictureURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?type=large", fbIdString]];
NSData *picData = [NSData dataWithContentsOfURL:profilePictureURL];
UIImage *fbPic = (UIImage *)[self.view viewWithTag:1001];
[fbPic initWithData:picData];
}
// Configure the cell...
return cell;
}
You need to actually assign the result of the initWithData: call to your fbPic image.
E.g.
fbPic = [fbPic initWithData: picData];
From the apple documentation on UIImage:
- (id)initWithData:(NSData *)data
Parameters
data -
The data object containing the image data.
Return Value
An initialized UIImage object, or nil if the method could not initialize the image from the specified data.
A couple of things:
UIImage *fbPic = (UIImage *)[self.view viewWithTag:1001]; - I think you're trying to get the UIImageView from the cell?
There's no UIImageView where you're actually showing the image.
It should be something like this:
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
NSURL *profilePictureURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?type=large", fbIdString]];
NSData *picData = [NSData dataWithContentsOfURL:profilePictureURL];
UIImageView *fbPicImageView = (UIImageView *)[self.view viewWithTag:1001];
[fbPicImageView setImage:[UIImage imageWithData:picData]];
}

how to show image in table cell through json parsing

NSURL *url = [NSURL URLWithString:#"yourimage"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[[UIImage alloc] initWithData:data] autorelease];
This code i used to get the image but how to show it in table cell.
try this,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSURL *url = [NSURL URLWithString:[imageArray objectAtIndex: [indexPath row]]];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[[UIImage alloc] initWithData:data] autorelease];
[[cell imageView] setImage:img];
return cell;
}
FirstLy You need To parse That JSON file In Your iOS Application.
I guess You get Some URL from That JSON for The Image So You need To Download Image Form That Prased URL and Can set That IMage Over ANy UIIMageView and you can set That UIIMageView to The Content View Of UITablViewCell.
Here You Need To Just Manage One THing Suppose You have Many Images To be Downlaod Form The Particular path.So You should Take Care of The UI Interaction also
Here Is Good Example Of How TO download Images form The URL and set That DownLoaded Image Over The UIImageView and set That UIImageView on to the ContentView of UITableViewcell.In this Example you'll also see The Way of How Can you Add The These Images Over The TableViewcEll.
Here Is The Link For That Example
I hope It may help You.
You can do it with
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
[[cell imageView] setImage:img];
But thats probably not going to run very well because you're downloading the images synchronously and that will most likely make your app stutter.
You should use lazy loading for the images, for an example take a look at
http://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html
This works for me:
NSURL *url = [NSURL URLWithString:[aTweet objectForKey:#"profile_image_url"]];
NSData *imgData = [NSData dataWithContentsOfURL:url];
cell.imageView.image = [UIImage imageWithData:imgData];

loading asynchronous images in tableview, they disappear at every scroll

I'm parsing an xml file, containing urls for thumb images. I want to show those thumbs in an uitableview.
Using class AsyncImageView (found on this website), my code works.
The only problem is this: every time that the user scrolls the uitableview, the images disappear for a moment... then re-appear (i think that i'm downloading the image every time but i'm not sure)!
That's an ugly effect, i want that if the image is downloaded, it stay visible.
this is my code (NB: in array_thumb there are the urls parsed before):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier;
static NSString *NibNamed;
UIDeviceOrientation deviceOrientation = [UIApplication sharedApplication].statusBarOrientation;
if (deviceOrientation != UIDeviceOrientationLandscapeLeft &&
deviceOrientation != UIDeviceOrientationLandscapeRight)
{
CellIdentifier= #"Cell1";
NibNamed = #"cell_gallery";
}
else
{
CellIdentifier= #"Cell2";
NibNamed = #"cell_gallery_landscape";
}
[[NSBundle mainBundle] loadNibNamed:NibNamed owner:self options:NULL];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:NibNamed owner:self options:nil];
cell = [nib objectAtIndex:0];
}
else {
AsyncImageView* oldImage = (AsyncImageView*)[cell.contentView viewWithTag:1];
[oldImage removeFromSuperview];
}
CGRect frame;
frame.size.width=72; frame.size.height=72;
frame.origin.x=10; frame.origin.y=10;
AsyncImageView* asyncImage = [[[AsyncImageView alloc] initWithFrame:frame] autorelease];
NSString *title = [NSString stringWithFormat:#"%#", [array_title objectAtIndex:indexPath.row]];
UILabel *testoLabel = (UILabel*)[cell viewWithTag:2];
testoLabel.text = title;
asyncImage.tag = 1;
NSLog(#"%#", asyncImage);
NSURL *url = [NSURL URLWithString:[array_thumb objectAtIndex:indexPath.row]];
asyncImage.layer.cornerRadius = 10.0;
asyncImage.layer.masksToBounds = YES;
[asyncImage loadImageFromURL:url];
[cell.contentView addSubview:asyncImage];
UIColor *miocolore1 = [[UIColor alloc] initWithRed:247.0 / 255 green:247.0 / 255 blue:247.0 / 255 alpha:1.0];
UIColor *miocolore2 = [[UIColor alloc] initWithRed:233.0 / 255 green:233.0 / 255 blue:233.0 / 255 alpha:1.0];
if (indexPath.row % 2 == 0) {
cell.contentView.backgroundColor = miocolore1;
}
else {
cell.contentView.backgroundColor = miocolore2;
}
return cell;
}
Nothing in your code or in AsyncImageView suggest that the images are cached so it seems the same image gets downloaded repeatedly.
AsyncImageView is using the following to load the image:
[NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy];
You probably want to make sure that caching is actually happening here by altering the cache policy.
I'd checkout ASIHTTPRequest which has a great cache implementation.
As the cell are reused, you have to provide the data yourself. Either you can save the downloaded image as NSData or UIImage and provide the url to download or you can use the already downloaded data.
This way it wont download the image everytime you scroll.