UITableView, Its jerking while scrolling - ios

/Problem is that, I created my own contentviews in UITableview and showing. While scrolling the table view is giving Jerking. How to resolve this issue./
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
/ImageDetails, I am receiving from server and loading using lazy loading./
UIImageView *lblImage = [[UIImageView alloc]initWithFrame:CGRectMake(10, 10, 60, 60)];
lblImage.contentMode = UIViewContentModeScaleAspectFill;
[cell.contentView addSubview:lblImage];
if([[[lArray objectAtIndex:indexPath.row] objectForKey:#"Foto"] length] > 0){
NSURL *imageURL = [NSURL URLWithString:[[lMovikidListArray objectAtIndex:indexPath.row] objectForKey:#"MovikitFoto"]];
NSString *key = [[[lArray objectAtIndex:indexPath.row] objectForKey:#"Foto"] MD5Hash];
NSData *data = [FTWCache objectForKey:key];
if (data) {
UIImage *image = [UIImage imageWithData:data];
lblImage.image = image;
} else {
lblImage.image = [UIImage imageNamed:#"defaultprofile.png"];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSData *data = [NSData dataWithContentsOfURL:imageURL];
[FTWCache setObject:data forKey:key];
UIImage *image = [UIImage imageWithData:data];
dispatch_sync(dispatch_get_main_queue(), ^{
lblImage.image = image;
});
});
}
CALayer *imageLayer = lblImage.layer;
[imageLayer setCornerRadius:lblImage.frame.size.width/2];
[imageLayer setMasksToBounds:YES];
}
else{
lblImage.image = [UIImage imageNamed:#"defaultprofile.png"];
}
UILabel *lblTitle = [[UILabel alloc]initWithFrame:CGRectMake(75, 10, 220, 25)];
lblTitle.text = [NSString stringWithFormat:#"%# - %#", [[lArray objectAtIndex:indexPath.row] objectForKey:#"Name"], [[lArray objectAtIndex:indexPath.row] objectForKey:#"SimNo"]];
lblTitle.font = [UIFont boldSystemFontOfSize:14.0f];
[cell.contentView addSubview:lblTitle];
UILabel *lblSubTitle = [[UILabel alloc]initWithFrame:CGRectMake(100, 40, 195, 35)];
if([[[lArray objectAtIndex:indexPath.row] objectForKey:#"Location"] length] <= 1){
lblSubTitle.text = LOCATION_NOT_AVAILABLE;
lImageName = #"caution_icon.png";
}
else{
lblSubTitle.text = [self calculateDistance:<some data>];
}
lblSubTitle.textColor = [UIColor darkGrayColor];
lblSubTitle.numberOfLines = 2;
lblSubTitle.font = [UIFont italicSystemFontOfSize:12.0f];
[cell.contentView addSubview:lblSubTitle];
/This image is a small image to show some indicators./
UIImageView *lblIndicatorImage = [[UIImageView alloc]initWithFrame:CGRectMake(75, 45, 20, 20)];
lblIndicatorImage.image = [UIImage imageNamed:lImageName];
[cell.contentView addSubview:lblIndicatorImage];
[cell setNeedsDisplay];

You cant do any UIKit operation on background thread. So just remove your graphical operation from background thread and it will be fine.
else {
lblImage.image = [UIImage imageNamed:#"defaultprofile.png"];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSData *data = [NSData dataWithContentsOfURL:imageURL];
[FTWCache setObject:data forKey:key];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:data];
lblImage.image = image;
});
});

Related

showing activity indicator within UIImageView

I am trying to add an activity indicator into an imageView as follows when I am downloading the contents from url but the problem is that the activity indicator is not visible.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = nil;
if ([imageArray count] >0){
if(cachedImage[[imageArray objectAtIndex:indexPath.row]] != nil){
recipeImageView.image = cachedImage[[imageArray objectAtIndex:indexPath.row]];
}
else{
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.frame = CGRectMake(140, 236, 37, 37);
[activityIndicator startAnimating];
[recipeImageView addSubview:activityIndicator];
self.view.userInteractionEnabled = NO;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
NSData *data0 = [NSData dataWithContentsOfURL: [NSURL URLWithString:[imageArray objectAtIndex:indexPath.row]]];
UIImage *image = [UIImage imageWithData: data0];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
recipeImageView.image = image;
[activityIndicator stopAnimating];
cachedImage[[imageArray objectAtIndex:indexPath.row]] = image;
});
});
}
}
How can i be able to show the activity indicator within imageview with progress percent if possible?
Just update your code and try this
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = nil;
if ([imageArray count] >0){
if(cachedImage[[imageArray objectAtIndex:indexPath.row]] != nil){
recipeImageView.image = cachedImage[[imageArray objectAtIndex:indexPath.row]];
}
else{
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[activityIndicator setCenter: recipeImageView.center];
[activityIndicator startAnimating];
[cell.contentView addSubview:activityIndicator];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
NSData *data0 = [NSData dataWithContentsOfURL: [NSURL URLWithString:[imageArray objectAtIndex:indexPath.row]]];
UIImage *image = [UIImage imageWithData: data0];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
recipeImageView.image = image;
[activityIndicator removeFromSuperview];
cachedImage[[imageArray objectAtIndex:indexPath.row]] = image;
});
});
}
}
Try this:
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.center = recipeImageView.center;
[activityIndicator startAnimating];
[recipeImageView addSubview:activityIndicator];
self.view.userInteractionEnabled = NO;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
NSData *data0 = [NSData dataWithContentsOfURL: [NSURL URLWithString:[imageArray objectAtIndex:indexPath.row]]];
UIImage *image = [UIImage imageWithData: data0];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
recipeImageView.image = image;
[activityIndicator stopAnimating];
[activityIndicator removeFromSuperview];
cachedImage[[imageArray objectAtIndex:indexPath.row]] = image;
});
});
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[indicator startAnimating];
[indicator setCenter:self.recipeImageView.center];
[self.contentView addSubview:indicator];

why same images are appearing while im scrolling my tabelview cell?

NSString *url = [NSString stringWithFormat:#"%#",[enclosureUrlArray objectAtIndex:indexPath.row]];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
([self.tableView cellForRowAtIndexPath:indexPath]);
dispatch_async(dispatch_get_main_queue(), ^{
cell.tag = indexPath.row;
UIImage *image = [UIImage imageWithData:imageData];
cell.IMGLabel.image = image;
[cell.IMGLabel setImage:image];
[cell.IMGLabel.layer setMasksToBounds:YES];
[cell.IMGLabel.layer setCornerRadius:2.5f];
[cell setNeedsLayout];
});
});

UITableView caching

I create a UITableView, the data comes through a JSON file quite heavy, I wondered if it was possible to put the tableView cached for what is not rafrachisse each segue (push for example)?
I would put my tableView cache for which loads faster loading this page.
My entries JSON (YouTube API v3):
- (void)fetchEntries
{
NSString *searchURL = [API_V3_CHANNEL_URL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *searchData = [NSData dataWithContentsOfURL:[NSURL URLWithString:searchURL]];
NSDictionary *searchDict =[NSJSONSerialization JSONObjectWithData:searchData options:NSJSONReadingMutableContainers error:nil];
self.readArray = [searchDict objectForKey:#"items"];
}
and my tableview code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomCell";
YouTubeCell *cell = (YouTubeCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Add utility buttons, si besoin effacer de ici
NSMutableArray *leftUtilityButtons = [NSMutableArray new];
[leftUtilityButtons sw_addUtilityButtonWithColor:
UIColorFromRGB(0x2c3e50)
icon:[UIImage imageNamed:#"Icon-message-swipe"]];
[leftUtilityButtons sw_addUtilityButtonWithColor:
UIColorFromRGB(0x475198)
icon:[UIImage imageNamed:#"IconFacebook2"]];
[leftUtilityButtons sw_addUtilityButtonWithColor:
UIColorFromRGB(0x4EA5EC)
icon:[UIImage imageNamed:#"IconTwitter2"]];
[leftUtilityButtons sw_addUtilityButtonWithColor:
UIColorFromRGB(0xe74c3c)
icon:[UIImage imageNamed:#"IconYoutube3"]];
cell.leftUtilityButtons = leftUtilityButtons;
cell.delegate = self;
// à ici
NSDictionary *searchResult = [self.readArray objectAtIndex:indexPath.row];
//Create the button and add it to the cell
//UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//[button addTarget:self
// action:#selector(customActionPressed:)
//forControlEvents:UIControlEventTouchDown];
//[button setTitle:#"Custom Action" forState:UIControlStateNormal];
//button.frame = CGRectMake(150.0f, 5.0f, 150.0f, 30.0f);
//[cell addSubview:button];
cell.ytTitle.text = [[searchResult objectForKey:#"snippet"] valueForKey:#"title"];
cell.ytLink.text = [[[searchResult objectForKey:#"snippet"] objectForKey:#"resourceId"] valueForKey:#"videoId"];
cell.ytLink.hidden = true;
cell.ytTitle.font = [UIFont fontWithName:#"BigNoodleTitling" size:17];
NSString *imageHD = [[[[searchResult objectForKey:#"snippet"] objectForKey:#"thumbnails"] objectForKey:#"high"] valueForKey:#"url"];
NSURL *imageURL = [NSURL URLWithString:imageHD];
NSString *key = imageHD;
NSData *data = [ISCache objectForKey:key];
if (data) {
UIImage *image = [UIImage imageWithData:data];
cell.ytThumbnail.image = image;
} else {
cell.ytThumbnail.image = [UIImage imageNamed:#"hqdefault.jpg"];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSData *data = [NSData dataWithContentsOfURL:imageURL];
[ISCache setObject:data forKey:key];
UIImage *image = [UIImage imageWithData:data];
dispatch_sync(dispatch_get_main_queue(), ^{
cell.ytThumbnail.image = image;
});
});
}
return cell;
}

Slow for loop, loading images from a Parse query into an array

Here is my code, I am having issues with it. It works, however it takes a very long time to load. I have the code within viewDidLoad. Also the self.playedGames and self.messages are NSArrays I got from querying two other classes.
newArray = [[NSMutableArray alloc]initWithCapacity:[self.playedGames count]];
messagesArray = [[NSMutableArray alloc]initWithCapacity:[self.messages count]];
ImageArray = [[NSMutableArray alloc]initWithCapacity:[self.playedGames count]];
PFQuery *query = [PFUser query];
[query orderByDescending:#"username"];
NSArray *Userarray1 = [query findObjects];
//NSLog(#"Userarray1 = %#",Userarray1);
PFFile *imageFile = [[PFFile alloc]init];
NSURL *imageFileUrl = [[NSURL alloc]init];
NSData *imageData = [[NSData alloc]init];
for(id i in Userarray1){
userPerson = [i valueForKey:#"username"];
for(id object in self.messages){
if([[object objectForKey:#"senderName"]isEqualToString:userPerson]){
imageFile = [i objectForKey:#"profilePic"];
if(imageFile !=nil){
imageFileUrl = [[NSURL alloc] initWithString:imageFile.url];
imageData = [NSData dataWithContentsOfURL:imageFileUrl];
newImageset = [UIImage imageWithData:imageData];
PFImageView *imgVew = [[PFImageView alloc] initWithFrame:CGRectMake(4, 5, 50, 50)];
imgVew.image = newImageset;
imgVew.opaque = YES;
[messagesArray addObject:imgVew];
}
else{
UIImage *NoPP = [UIImage imageNamed:#"friends_tab.png"];
NoPP = [self imageScaledToSize:CGSizeMake(50, 50)];
PFImageView *NoPPView = [[PFImageView alloc]initWithFrame:CGRectMake(4, 5, 50, 50)];
NoPPView.image = NoPP;
NoPPView.opaque = YES;
[messagesArray addObject:NoPPView];
}
}
}
//step two
for(id object in self.playedGames){
if([[object objectForKey:#"yourName"] isEqualToString:userPerson]){
imageFile = [i objectForKey:#"profilePic"];
if(imageFile !=nil){
imageFileUrl = [[NSURL alloc] initWithString:imageFile.url];
imageData = [NSData dataWithContentsOfURL:imageFileUrl];
newImageset = [UIImage imageWithData:imageData];
PFImageView *imgVew = [[PFImageView alloc] initWithFrame:CGRectMake(4, 5, 50, 50)];
imgVew.image = newImageset;
imgVew.opaque = YES;
[ImageArray addObject:imgVew];
//NSLog(#"ImageArray = %#",ImageArray);
}
else{
UIImage *NoPP = [UIImage imageNamed:#"friends_tab.png"];
NoPP = [self imageScaledToSize:CGSizeMake(50, 50)];
PFImageView *NoPPView = [[PFImageView alloc]initWithFrame:CGRectMake(4, 5, 50, 50)];
NoPPView.image = NoPP;
NoPPView.opaque = YES;
[ImageArray addObject:NoPPView];
}
}
}
}
Two really big problems.
The [query findObjects]; is synchronous, meaning that it does not return until complete. This needs to happen in the background. Take a look at one of the findInBackground methods offered by Parse.
Within your loop, you are loading image resource from a URL by calling imageData = [NSData dataWithContentsOfURL:imageFileUrl];. Again, this is synchronous and will wait until one image is loaded before moving on to the next. These image loads need to be made asynchronous as well.
worked around it and added this
NSURL *imageFileUrl = [[NSURL alloc] initWithString:imageFile.url];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
NSData *imageData = [NSData dataWithContentsOfURL:imageFileUrl];
newImageset = [UIImage imageWithData:imageData];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
PFImageView *imgVew = [[PFImageView alloc] initWithFrame:CGRectMake(4, 5, 50, 50)];
imgVew.image = newImageset;
imgVew.opaque = YES;
[messagesArray addObject:imgVew];
});
loadingthesearches1 = YES;
[self ReloadTheData];
});
and it worked 90% faster

NSOperationQueue Issue

I have a code that i used as a image downloder in ios 6 but when i use same code in different application that used ios 5 it gives me error NSInvalidArgumentException', reason: '-[NSNull length]: unrecognized selector sent to instance hear is the code that i am using
[self.imageDownloadingQueue addOperationWithBlock:^{
NSURL *imageUrl = [NSURL URLWithString:ImageURL];
NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
UIImage *images = nil;
if (imageData)
images = [UIImage imageWithData:imageData];
if (images){
[self.imageCache setObject:images forKey:ImageURL];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// make sure the cell is still visible
imageV.image = images;
}];
}
}];
Can anybody tell me what i am doing wrong coz this code is help me a lot when downloading image separately. Thank you
PS Whole function that i am using
-(void) setScrollView:(UIScrollView *)scrollview :(NSArray *)contentArray{
int x = 0;
int i = 0;
NSString *ImageURL=#"http://www.online-image-editor.com/styles/2013/images/example_image.png";
for(NSDictionary *str in contentArray){
UIImageView *imageV = [[UIImageView alloc ] initWithFrame:CGRectMake(x, 0, 200,125)];
#try {
ImageURL = [str objectForKey:#"image"];
}
#catch (NSException * e) {
NSLog(#"Exception: %#", [e description]);
}
imageV.userInteractionEnabled = YES;
ImageTapGesture *singleTap = [[ImageTapGesture alloc] initWithTarget:self action:#selector(tapDetectedMain:)];
singleTap.newItem = str;
singleTap.currentItem = i ;
singleTap.numberOfTapsRequired = 1;
[imageV addGestureRecognizer:singleTap];
UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(x,125,200,20)];
[title setFont:[UIFont systemFontOfSize:11]];
title.numberOfLines = 2;
title.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[title setBackgroundColor:[UIColor blackColor]];
[title setTextColor:[UIColor whiteColor]];
title.text = [NSString stringWithFormat:#" %#",[str objectForKey:#"title"]];
x += title.frame.size.width+2;
UIImage *cachedImage = [self.imageCache objectForKey:ImageURL];
if (cachedImage){
imageV.image = cachedImage;
}
else{
imageV.image = [UIImage imageNamed:#"vdo.png"];
[self.imageDownloadingQueue addOperationWithBlock:^{
NSURL *imageUrl = [NSURL URLWithString:ImageURL];
NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
UIImage *images = nil;
if (imageData)
images = [UIImage imageWithData:imageData];
if (images){
[self.imageCache setObject:images forKey:ImageURL];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// make sure the cell is still visible
imageV.image = images;
}];
}
}];
}
[scrollview addSubview:imageV];
[scrollview addSubview:title];
}
scrollview.contentSize = CGSizeMake(x, scrollview.frame.size.height);
i++;
}
You should definitely check the ImageURL you are sending into the operation. It seems, this ImageURL is [NSNull null].
If it is a local variable, is it declared as __block NSString *ImageUrl?
pls try this code:
[self.imageDownloadingQueue addOperationWithBlock:^{
NSURL *imageUrl ;
if((ImageURL!=nil)&&(![ImageURL isKindOfClass:[NSNull class]]))
{
imageUrl= [NSURL URLWithString:ImageURL];
}
NSData *imageData;
if((imageUrl!=nil)&&(![imageUrl isKindOfClass:[NSNull class]]))
{
imageData = [NSData dataWithContentsOfURL:imageUrl];
}
UIImage *images = nil;
if((imageData!=nil)&&(![imageData isKindOfClass:[NSNull class]]))
images = [UIImage imageWithData:imageData];
if((images!=nil)&&(![images isKindOfClass:[NSNull class]]))
{
[self.imageCache setObject:images forKey:ImageURL];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// make sure the cell is still visible
imageV.image = images;
}];
}
}];
Hope this will help you.

Resources