How to use SDWebImage - ios

I have UITableViewCell and in this load images, so I want to images load Asynchronies and show activate indicator. This time images loading time is very high and all images load after images show on table view. many times images cant load and user UIInterface is hang. and do not work any process in application.. I am very tired, I used a SDWebImage library. please help how it possible, Thank You
#import "UIImageView+WebCache.h"
#interface pictureViewController ()
{
NSArray*picarray;
NSArray*titlearray;
NSArray*idarray;
}
#end
#implementation pictureViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[[self navigationController] navigationBar] setTitleTextAttributes:#{NSForegroundColorAttributeName: [UIColor whiteColor]}];
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"background2.png"] forBarMetrics:UIBarMetricsDefault];
_tableview.separatorColor = [UIColor yellowColor];
NSURLRequest *req=[[NSURLRequest alloc]initWithURL:[NSURL URLWithString:#"http://edutimeapp.com/toshow/chamber-of-commerc/ws/fetch_gallery.php"]];
response =[[NSMutableData alloc]init];
[NSURLConnection connectionWithRequest:req delegate:self];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[response appendData:data];
NSLog(#"error receving data %#",response);
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError *error;
//NSLog(#"Error in receiving data %#",error);
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];
// NSLog(#"response data %#",json);
NSArray *results = [json objectForKey:#"status"];
picarray = [results valueForKey:#"img_url"];
titlearray = [results valueForKey:#"title"];
// NSLog(#"my title is%#",titlearray);
idarray=[results valueForKey:#"id"];
//NSLog(#"my galary id is%#",idarray);
[self.tableview reloadData];
}
// Do any additional setup after loading the view, typically from a nib.
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [picarray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// NSLog(#"tableview cell");
picture_viewcontrollerCell *cell = [tableView dequeueReusableCellWithIdentifier:#"htr"];
if (cell==nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"Cell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
//NSData* imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString: [picarray objectAtIndex:indexPath.row]]];
// UIImage* image = [[UIImage alloc] initWithData:imageData];
//cell.picture.image =image;
cell.titlelbl.text=[NSString stringWithFormat:#"%#",[titlearray objectAtIndex:indexPath.row]];
NSURL*url= [[picarray objectAtIndex:indexPath.row]valueForKey:#"img_url"];
[cell.picture setContentMode:UIViewContentModeScaleAspectFill];
[cell.picture sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:#"Placeholder.jpg"]];
return cell;
}
#end

You should try this (Show activityIndicator & Load Image using SDWebImage)-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// NSLog(#"tableview cell");
picture_viewcontrollerCell *cell = [tableView dequeueReusableCellWithIdentifier:#"htr"];
if (cell==nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"Cell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.titlelbl.text=[NSString stringWithFormat:#"%#",[titlearray objectAtIndex:indexPath.row]];
NSURL*url= [NSURL URLWithString:[NSString stringWithFormat:#"%#",[picarray objectAtIndex:indexPath.row]]];
[cell.picture setContentMode:UIViewContentModeScaleAspectFill];
[cell.picture setShowActivityIndicatorView:YES];
[cell.picture setIndicatorStyle:UIActivityIndicatorViewStyleGray];
[cell.picture sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:#"placeHolder.png"] options:indexPath.row == 0 ? SDWebImageRefreshCached : 0];
return cell;
}

Are you sure your code can even compile? In your cellForRowAtIndexPath I see [cell.picture sd_setImageWithURL:imageData placeholderImage:[UIImage imageNamed:#"Placeholder.jpg"]];
when you commented off your declaration of imageData.
Even if you didn't comment, this line should be
[cell.picture sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:#"Placeholder.jpg"]];

you have to use
NSURL*url= [[picarray objectAtIndex:indexPath.row]valueForKey:#"img_url"];
[cell.picture setContentMode:UIViewContentModeScaleAspectFill];
[cell.picture sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:#"Placeholder.jpg"]];
instead of
NSURL*url= [[picarray objectAtIndex:indexPath.row]valueForKey:#"img_url"];
[cell.picture setContentMode:UIViewContentModeScaleAspectFill];
[cell.picture sd_setImageWithURL:imageData placeholderImage:[UIImage imageNamed:#"Placeholder.jpg"]];
you have to pass url directly instead of imageData

Try this code :
Add UIActivityIndicatorView in tableview cell.
Changed following code in your cellForRowAtIndexpath.
cell.activityIndicator.center = imageView.center;
cell.activityIndicator.hidesWhenStopped = YES;
NSURL *url= [[picarray objectAtIndex:indexPath.row]valueForKey:#"img_url"];
[cell.picture sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:#"placeholder.png"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
[cell.activityIndicator stopAnimating];
}];
[cell.picture addSubview:activityIndicator];
[cell.activityIndicator startAnimating];

Related

How to load images from API/URL asynchronously?

I am fetching images synchronously from an array which stores URLs of images but it work very slowly. Now i want to load them asynchronously for fast working.
Heres the code and provide answer with coding.
#import "DetailViewController.h"
#import "FinalViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
#synthesize jsonData;
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Select a Photo";
// Do any additional setup after loading the view.
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"http://json.code.com/albums/1/photos"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(nonnull NSURLResponse *)response
{
data1 = [[NSMutableData alloc] init];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(nonnull NSData *)theData
{
[data1 appendData:theData];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
jsonArray1 = [NSJSONSerialization JSONObjectWithData:data1 options:nil error:nil];
[mainTableView reloadData];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(nonnull NSError *)error
{
UIAlertView *errorView = [[UIAlertView alloc]initWithTitle:#"Error" message:#"Please make sure you are connected to either 3G or Wi-Fi." delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil, nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (int)numberOfSectionInTableView:(UITableView *)tableView
{
return 1;
}
- (int) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [jsonArray1 count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
cell.textLabel.text = [[jsonArray1 objectAtIndex:indexPath.row] objectForKey:#"title"];
cell.detailTextLabel.text = [NSString stringWithFormat:#"URL : %#", [[jsonArray1 objectAtIndex:indexPath.row] objectForKey:#"url"]];
NSURL *URL = [[NSURL alloc] initWithString:[[jsonArray1 objectAtIndex:indexPath.row] valueForKey:#"thumbnailUrl"]];
NSData *URLData = [[NSData alloc] initWithContentsOfURL:URL];
[[cell imageView]setImage:[UIImage imageWithData:URLData]];
return cell;
}
-(void)tableView:(UITableView *)tableview didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
FinalViewController *fvc = [[FinalViewController alloc] initWithNibName:#"FinalViewController" bundle:nil];
fvc.jsonData2 = [jsonArray1 objectAtIndex:indexPath.row];
[self.navigationController pushViewController:fvc animated:YES];
}
#end
We can use dispatch_async to run the operation asynchronously.
Try this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
myCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
cell = [[myCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
cell.poster.image = nil; // or cell.poster.image = [UIImage imageNamed:#"placeholder.png"];
dispatch_async(kBgQueue, ^{
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://myurl.com/%#.jpg",[[myJson objectAtIndex:indexPath.row] objectForKey:#"movieId"]]]];
if (imgData) {
UIImage *image = [UIImage imageWithData:imgData];
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
myCell *updateCell = (id)[tableView cellForRowAtIndexPath:indexPath];
if (updateCell)
updateCell.poster.image = image;
});
}
}
});
return cell;
}
You can do like this:
cell.tag = indexPath.row;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^(void) {
NSData *imageData = [NSData dataWithContentsOfURL: URL];
UIImage* image = [[UIImage alloc] initWithData:imageData];
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
if (cell.tag == indexPath.row) {
cell.imageView.image = image;
[cell setNeedsLayout];
}
});
}
});
Ref: Asynchronous downloading of images for UITableView with GCD
Just by simply setting the following works fine for me .
cell.imageView.image =[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",[imageArray objectAtIndex:i]]]]];
You can use the activity indicator as you have asked . Just drag and drop UIActivityIndicatorView onto the UIImageView of the UITableViewCell and set the needed constraints . Once the image gets loaded you can set it as hidden .
To do it programmatically , you can add a subview to the Image view in the UITableViewCell. Once the Image gets loaded you can remove the sub view .
UIActivityIndicatorView* actInd = [[UIActivityIndicatorView alloc]init];
[cell.imageView addSubview:actInd];

Async Image Loading Performance

I am loading images in UITableViewCell receiving from url using below code, everything is working fine but the image load very slow in UITableViewCell and if i think as a user, it is not acceptable.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [checkData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger i =indexPath.row;
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
UIImageView propertyImage = (UIImageView *)[cell viewWithTag:10];
NSString *test = [[checkData objectAtIndex:i]valueForKey:#"image"];
CGRect frame=propertyImage.bounds;
AsyncImageView asyImage=[[AsyncImageView alloc] initWithFrame:frame];
[asyImage setImage:[UIImage imageNamed:#"loading.png"]];
self.urlForTesting=[NSURL URLWithString:test];
[asyImage loadImageFromURL:self.urlForTesting];
asyImage.imageURL =self.urlForTesting;
asyImage.contentMode = UIViewContentModeScaleToFill;
asyImage.layer.masksToBounds=YES;
[propertyImage addSubview:asyImage];
return cell;
}
Use AFNetworking Class & add additional two file to download from github "UIImageView+AFNetworking" and import in your project. then after add this code from "cellForRowAtIndexPath"
// Fetch Image from URL
NSURL *url = [NSURL URLWithString:[[checkData objectAtIndex:i]valueForKey:#"image"]];
[objWinner.actWinner startAnimating];
[objWinner.actWinner setHidden:NO];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
[objWinner.imgwinner setImageWithURLRequest:req placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image){
[objWinner.actWinner stopAnimating]; // this is Activityindicator
[objWinner.actWinner setHidden:YES];
objWinner.imgwinner.image = image;
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){
}];

Asynchronously set images in tableview

I have a TableView using custom cells. I initially was setting grabbing an image from a URL in the cellForRowAtIndexPath method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = (SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSDictionary *dictObject = [places objectAtIndex:indexPath.row];
cell.nameLabel.text = [dictObject valueForKey:#"PlaceTitle"];
NSURL *url = [NSURL URLWithString:#"http://images1.fanpop.com/images/image_uploads/Mario-Kart-Wii-Items-mario-kart-1116309_600_600.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
cell.thumbnailImageView.image = image;
return cell;
}
but this was making my TableView scroll laggy. Once I removed the image fetch, it scrolled fine, so I know this is my problem.
My question is: how can I asynchronously fetch this image and set it in my cell? Is there an easy way to do this? Thanks!
Step 1: Have a cache containing images. Either just in memory, better on disk.
Step 2: When you need an image, call a method which either returns an image from the cache, or returns a default image and starts a download.
Step 3: When a download finishes, add the image to the cache. Then find out which rows need the image. Reload all the rows that reload the image.
The download should be done asynchronously using GCD. I would really recommend that you add the download code into a separate, reusable method so that you can handle download errors. Even if you don't do it now, you will do it later.
dataWithContentsOfURL is a synchronous method rather than asynchronous,as
Apple Documents described.
This method is ideal for converting data:// URLs to NSData objects, and can also be used for reading short files synchronously. If you need to read potentially large files, use inputStreamWithURL: to open a stream, then read the file a piece at a time.
In order to asynchronously load image,especially in tableViewCell,try use 3rd part Library SDWebImage
Use this code inside your tableviews cellforindexpath
NSURLRequest *req =[[NSURLRequest alloc]initWithURL:[NSURL URLWithString:#"yourimageurl.com"]];
[NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if(!error){
UIImage *image =[UIImage imageWithData:data];
cell.thumbnailImageView.image = image;
}
else{
//error
}
}];
Create UIImageView Class File (i named it to MJTableImageView).
in MJTableImageView.h File
#interface MJTableImageView : UIImageView< NSURLConnectionDelegate, NSURLConnectionDataDelegate >
{
NSMutableData *imageData ;
long long expectedLength;
NSURLConnection *currentConnection;
NSString *File_name;
}
#property(nonatomic,readonly)UIActivityIndicatorView *loadingIndicator;
#property(nonatomic)BOOL showLoadingIndicatorWhileLoading;
-(void)setImageUrl:(NSURL *)imageUrl fileName:(NSString *)name;
#end
in MJTableImageView.m File
-(void)setImageUrl:(NSURL *)imageUrl fileName:(NSString *)name
{
// discard the previous connection
if(currentConnection)
{
[currentConnection cancel];
}
File_name = name;
//reset current image
self.image = nil;
// if(_showLoadingIndicatorWhileLoading)
// {
//show the loading indicator
if(!_loadingIndicator)
{
CGFloat width = self.bounds.size.width*0.5;
_loadingIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake((self.bounds.size.width-width)/2, (self.bounds.size.height-width)/2, 25.0 , 25.0)];
_loadingIndicator.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.5];
_loadingIndicator.layer.cornerRadius = width*0.1;
}
[self startLoadingIndicator];
// }
// initialize the placeholder data
imageData = [NSMutableData data];
// start the connection
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:imageUrl];
request.cachePolicy = NSURLRequestUseProtocolCachePolicy;
currentConnection = [NSURLConnection connectionWithRequest:request delegate:self];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//if the image view is reused in a table view for example to load another image previous image is discarded
if(connection != currentConnection)
{
[connection cancel];
[self cleanUp];
return;
}
// append new Data
[imageData appendData:data];
// show the partially loaded image
self.image = [UIImage imageWithData:imageData];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
expectedLength = response.expectedContentLength;
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
// clean up
[self cleanUp];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// show the full image
self.image = [UIImage imageWithData:imageData];
NSString *filename = [NSHomeDirectory() stringByAppendingFormat:#"/Documents/%#", File_name];
NSData *data = UIImagePNGRepresentation([UIImage imageWithData:imageData]);
[data writeToFile:filename atomically:YES];
// clean up
[self cleanUp];
}
-(void)cleanUp
{
// clean up
imageData = nil;
[self stopLoadingIndicator];
}
-(void)startLoadingIndicator
{
if(!_loadingIndicator.superview)
{
[self addSubview:_loadingIndicator];
}
[_loadingIndicator startAnimating];
}
-(void)stopLoadingIndicator
{
if(_loadingIndicator.superview)
{
[_loadingIndicator removeFromSuperview];
}
[_loadingIndicator stopAnimating];
}
I am using StoryBoard so i add ImageClass(MJTableImageView) file to UItableviewcell ImageView and set tag number to it.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *dict = [self.arr objectAtIndex:indexPath.row];
UITableViewCell *cell = [self.MJTableView dequeueReusableCellWithIdentifier:#"MJImageCell"];
if(cell == nil)
{
}
UILabel *appName = (UILabel*)[cell.contentView viewWithTag:2];
appName.text = [dict valueForKey:#"trackName"];
MJTableImageView *imageview = (MJTableImageView *)[cell.contentView viewWithTag:1];
NSString *url = [dict valueForKey:#"artworkUrl60"];
NSString *filename = [NSHomeDirectory() stringByAppendingFormat:#"/Documents/%#",[dict valueForKey:#"trackName"] ];
NSData *data = [NSData dataWithContentsOfFile:filename];
if(data)
{
imageview.image = [UIImage imageWithData:data];
}
else
{
[imageview setImageUrl:[NSURL URLWithString:url] fileName:[dict valueForKey:#"trackName"]];
}
return cell;
}
For More details see Github Project MJTableImageSwift it is in Swift.

Parse an image in to the Collection-view Custom cell in ios

i want to parse an image from web services and show onto the collection view custom cell for this i write a code as
in my .h file
#property(strong,nonatomic)IBOutlet UICollectionView *imagecollection;
#property(strong,nonatomic)NSArray *imagesa;
#property(strong,nonatomic)NSDictionary *json;
#property(strong,nonatomic)NSArray *aimages;
and in my .m file
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)
#define imageURL [NSURL URLWithString:#"http://www.truemanindiamagazine.com/webservice/gallery_image.php"]
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(kBgQueue, ^{
data = [NSData dataWithContentsOfURL: imageURL];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
[self.imagecollection registerNib:[UINib nibWithNibName:#"Custumcell" bundle:nil] forCellWithReuseIdentifier:#"CellIdentifier"];
}
-(void)fetchedData:(NSData *)responsedata
{
NSError* error;
self.json = [NSJSONSerialization JSONObjectWithData:responsedata options:kNilOptions error:&error];
self.imagesa=[json objectForKey:#"data"];
NSLog(#"images,%#",self.imagesa);
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.imagesa.count;
}
-(Custumcell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
Custumcell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"CellIdentifier" forIndexPath:indexPath];
UIImageView *img=[[UIImageView alloc]initWithFrame:CGRectMake(0,0,100,100)];
NSString *img2=[self.imagesa objectAtIndex:indexPath.row];
img.image=[UIImage imageNamed:img2];
cell.imageview.image=[UIImage imageNamed:img2];
return cell;
}
then images from web services is parsed but not shown into the collection view please give me any solution.
try to replace your
-(void)fetchedData:(NSData *)responsedata
{
NSError* error;
self.json = [NSJSONSerialization JSONObjectWithData:responsedata options:kNilOptions error:&error];
self.imagesa=[json objectForKey:#"data"];
NSLog(#"images,%#",self.imagesa);
}
with the code
-(void)fetchedData:(NSData *)responsedata
{
NSError* error;
self.json = [NSJSONSerialization JSONObjectWithData:responsedata options:kNilOptions error:&error];
self.imagesa=[json objectForKey:#"data"];
if (self.imagesa.count) {
dispatch_async(dispatch_get_main_queue(), ^{
[imagecollection reloadData];
});
}
NSLog(#"images,%#",self.imagesa);
}
now use SDWebImageDownloader and inside your cellForRowAtIndexpath method, replace your method cellForRowAtIndexPath with
Custumcell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"CellIdentifier" forIndexPath:indexPath];
NSDictionary *dict = [self.imagesa objectAtIndex:indexPath.item];
NSString *img2=[dict valueForKey:#"link"];
[cell.imageview sd_setImageWithURL:[NSURL URLWithString:[img2 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] placeholderImage:[UIImage imageNamed:#"temp.png"] options:SDWebImageProgressiveDownload completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"downloaded");
});
}];
return cell;
also import #import "UIImageView+WebCache.h" in your file
May be this will help you.
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
-(Custumcell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
Custumcell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"CellIdentifier" forIndexPath:indexPath];
cell.imageview.image= nil; // or cell.poster.image = [UIImage imageNamed:#"placeholder.png"];
dispatch_async(kBgQueue, ^{
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[self.imagesa objectAtIndex:indexPath.row] objectForKey:#"link"]]];
if (imgData) {
UIImage *image = [UIImage imageWithData:imgData];
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
Custumcell *updateCell = (id)[collectionView cellForItemAtIndexPath:indexPath];
if (updateCell)
updateCell.imageview.image = image;
});
}
}
});
return cell;
}

Scrolling issue Table View with JSON data

I'm parsing some data from a JSON-file located on my server to my Table View.
When I launch the app the app successfully downloads the data to my table view, but when I begin to scroll, the app crashes.
Here's my code:
#import "FirstViewController.h"
#import "YoutubePost.h"
#import "AFNetworking.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize tableView = _tableView, activityIndicatorView = _activityIndicatorView, movies = _movies;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Videos", #"Videos");
self.tabBarItem.image = [UIImage imageNamed:#"newtab1"];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.navigationController setNavigationBarHidden:YES];
self.tableView.separatorColor = [UIColor clearColor];
// Setting Up Activity Indicator View
self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.activityIndicatorView.hidesWhenStopped = YES;
self.activityIndicatorView.center = self.view.center;
[self.view addSubview:self.activityIndicatorView];
[self.activityIndicatorView startAnimating];
self.tableView.separatorColor = [UIColor clearColor];
// Initializing Data Source
self.movies = [[NSArray alloc] init];
NSURL *url = [[NSURL alloc] initWithString:#"http://my-website.com/link-to-json.php?name=Name&orderby=published"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
self.movies = JSON;
[self.activityIndicatorView stopAnimating];
[self.tableView reloadData];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation start];
}
// Table View Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.movies && self.movies.count) {
return self.movies.count;
} else {
return 0;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 378;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"YoutubePost";
YoutubePost *cell = (YoutubePost *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"YoutubePost" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
cell.title.text = [movie objectForKey:#"title"];
NSURL *url = [[NSURL alloc] initWithString:[movie objectForKey:#"link"]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
NSString * storyLink = [[_movies objectAtIndex: storyIndex] objectForKey:#"link"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:storyLink]];
NSString *formattedJSON = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:[self.tweets objectAtIndex:indexPath.row] options:NSJSONWritingPrettyPrinted error:nil] encoding:NSUTF8StringEncoding];
NSLog(#"tweet:\n%#", formattedJSON);
}
#end
What is wrong? I see that the data successfully downloads to my custom Table View Cell, but every time I try to scroll down the app crashes. Please help me fix this.
Thanks.
Correct this:
// Initializing Data Source
//self.movies = [[NSArray alloc] init];
NSURL *url = [[NSURL alloc] initWithString:#"http://my-website.com/link-to-json.php?name=Name&orderby=published"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
self.movies = [[NSArray alloc] initWithArray:JSON];
[self.activityIndicatorView stopAnimating];
[self.tableView reloadData];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation start];
And in your YouTubePost Nib add Identifier "YouTubePost":
And also in your YouTubePost Nib select your title UILabel and in the inspector change from:
To:
Or Change:
To:
This will do the job.
Change the lines below:
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"YoutubePost" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
Like this:
if (cell == nil)
{
UINib *nib = [UINib nibWithNibName:#"YoutubePost" bundle:nil];
[tableView registerNib:nib forCellReuseIdentifier:#"YoutubePost"];
tableViewCell = [tableView dequeueReusableCellWithIdentifier:#"YoutubePost"];
}
It looks like you're not doing any checking for [NSNull null] in your JSON. It is possible that the following code will give you [NSNull null] instead of an NSDictionary:
NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
You should filter these out before calling reloadData
Similarly, this line could also potentially return [NSNull null]:
cell.title.text = [movie objectForKey:#"title"];
You need to be prepared to handle that case. This may help you: Replace all NSNull objects in an NSDictionary

Resources