UITableView image loading with json is not loading properly - ios

I am using this to display some labels and images by JSON parsing in to tableView but images are not coming at the first launch when scrolling the tableview images are coming and dancing i mean not coming in order format help me with this
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
self.customCellClass = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (self.customCellClass == nil)
{
self.customCellClass = [[CellCustom alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
self.customCellClass.nameLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:#"name"]; // label
self.customCellClass.cityLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:#"region"]; // label
NSString * stripped = [[[arrayData objectAtIndex:indexPath.row] objectForKey:#"summary"] stripHtml]; //label
self.customCellClass.detailLabel.text = stripped;
self.customCellClass.mainImage.image = nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
NSData *data0 = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:#"images"]objectForKey:#"logo"]]];
UIImage *image = [UIImage imageWithData:data0];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
self.customCellClass.mainImage.image = image;
});
});
return self.customCellClass;
}

Replace below code in UITableView's cellForRowAtIndexPath method :
//Check if cell has image or not
if(!self.customCellClass.mainImage.image)
{
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(q, ^{
NSData *data0 = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:#"images"]objectForKey:#"logo"]]];
UIImage *image = [UIImage imageWithData:data0];
//Get main queue
dispatch_async(dispatch_get_main_queue(), ^{
/* This is the main thread again, where we set the tableView's image to be what we just fetched. */
self.customCellClass.mainImage.image = image;
});
});
}
Good solution is if you are using AFNetworking then use UIImageView+AFNetworking category
NSURL *imageURL = [NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:#"images"]objectForKey:#"logo"]]
[self.customCellClass.mainImage setImageWithURL:imageURL placeholderImage:nil];

You are assigning image=nil every time when cell is loading and downloading the same image.
You can user following class to do this seamlessly.
AsyncImageView.h
#import <UIKit/UIKit.h>
#interface AsyncImageView : UIView {
NSURLConnection *connection;
NSMutableData *data;
NSString *urlString; // key for image cache dictionary
}
-(void)loadImageFromURL:(NSURL*)url;
-(void)loadBackgroundImage:(UIImage *)image;
-(UIImage*)loadImageFromURLForGetIamge:(NSURL*)url;
-(BOOL)getCachedImageWithUrl:(NSString*)url;
#end
and AsyncImageView.m
#import "AsyncImageView.h"
#import "ImageCacheObject.h"
#import "ImageCache.h"
//
// Key's are URL strings.
// Value's are ImageCacheObject's
//
static ImageCache *imageCache = nil;
#define SPINNY_TAG 5555
#implementation AsyncImageView
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
}
return self;
}
- (void)drawRect:(CGRect)rect {
// Drawing code
}
- (void)dealloc {
[connection cancel];
}
-(void)loadBackgroundImage:(UIImage *)image
{
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.layer.masksToBounds=YES;
//imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout];
[self setNeedsLayout];
imageView=nil;
}
-(void)loadImageFromURL:(NSURL*)url
{
if (connection != nil) {
[connection cancel];
connection = nil;
}
if (data != nil) {
data = nil;
}
if (imageCache == nil) // lazily create image cache
imageCache = [[ImageCache alloc] initWithMaxSize:2*1024*1024]; // 2 MB Image cache
// NSLog(#"Value of the url here = %#",url);
urlString = [[url absoluteString] copy];
UIImage *cachedImage = [imageCache imageForKey:urlString];
if (cachedImage != nil)
{
if ([[self subviews] count] > 0)
{
[[[self subviews] objectAtIndex:0] removeFromSuperview];
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:cachedImage];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.layer.masksToBounds=YES;
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout]; // is this necessary if superview gets setNeedsLayout?
[self setNeedsLayout];
imageView=nil;
return;
}
UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinny.tag = SPINNY_TAG;
spinny.frame=CGRectMake(self.frame.size.width/2-10, self.frame.size.height/2-10, 20, 20);
spinny.center = self.center;
[spinny startAnimating];
[self addSubview:spinny];
[self bringSubviewToFront:spinny];
spinny=nil;
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
-(BOOL)getCachedImageWithUrl:(NSString*)url
{
BOOL isIamgeCached=NO;
if (imageCache == nil)
imageCache = [[ImageCache alloc] initWithMaxSize:2*1024*1024]; // 2 MB Image cache
UIImage *cachedImage = [imageCache imageForKey:url];
if (cachedImage != nil)
{
isIamgeCached=YES;
}
return isIamgeCached;
}
-(UIImage*)loadImageFromURLForGetIamge:(NSURL*)url
{
if (connection != nil)
{
[connection cancel];
connection = nil;
}
if (data != nil)
{
data = nil;
}
if (imageCache == nil) // lazily create image cache
imageCache = [[ImageCache alloc] initWithMaxSize:2*1024*1024]; // 2 MB Image cache
// NSLog(#"Value of the url here = %#",url);
urlString = [[url absoluteString] copy];
UIImage *cachedImage = [imageCache imageForKey:urlString];
if (cachedImage != nil)
{
if ([[self subviews] count] > 0)
{
[[[self subviews] objectAtIndex:0] removeFromSuperview];
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:cachedImage];
imageView.contentMode = UIViewContentModeScaleToFill;
imageView.autoresizingMask =
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout]; // is this necessary if superview gets setNeedsLayout?
[self setNeedsLayout];
imageView=nil;
return cachedImage;
}
UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinny.tag = SPINNY_TAG;
spinny.frame=CGRectMake(self.frame.size.width/2-10, self.frame.size.height/2-10, 20, 20);
//spinny.center = self.center;
[spinny startAnimating];
[self addSubview:spinny];
[self bringSubviewToFront:spinny];
spinny=nil;
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:20.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
return cachedImage;
}
- (void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)incrementalData {
if (data==nil)
{
data = [[NSMutableData alloc] initWithCapacity:2048];
}
[data appendData:incrementalData];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection
{
connection = nil;
UIView *spinny = [self viewWithTag:SPINNY_TAG];
[spinny removeFromSuperview];
if ([[self subviews] count] > 0)
{
[[[self subviews] objectAtIndex:0] removeFromSuperview];
}
UIImage *image = [UIImage imageWithData:data];
[imageCache insertImage:image withSize:[data length] forKey:urlString];
UIImageView *imageView = [[UIImageView alloc]
initWithImage:image];
imageView.contentMode = UIViewContentModeScaleToFill;
imageView.autoresizingMask =
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout]; // is this necessary if superview gets setNeedsLayout?
[self setNeedsLayout];
imageView=nil;
data = nil;
}
#end

You use dispatch_async to load image from remote, that means the images to be displayed in tableview cells are loaded asynchronously. And you use a instance variable to record current cell, which cause the problem you met.
After a image being loaded finished (may take few minutes), it want to be displayed in a cell (written in this code),
dispatch_sync(dispatch_get_main_queue(), ^(void) {
self.customCellClass.mainImage.image = image;
});
only to find that the self.customCellClass points to a wrong cell (the - (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath was called several times during the image being loaded, and each calling changes the pointing of self.customCellClass to other cell).
So, the order of images is wrong.
Try this:
Use a locality variable to keep the cell get from dequeueReusableCellWithIdentifier. Like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
CellCustom *customCellClass = (CellCustom *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (customCellClass == nil)
{
customCellClass = [[CellCustom alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
customCellClass.nameLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:#"name"]; // label
customCellClass.cityLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:#"region"]; // label
NSString * stripped = [[[arrayData objectAtIndex:indexPath.row] objectForKey:#"summary"] stripHtml]; //label
customCellClass.detailLabel.text = stripped;
customCellClass.mainImage.image = nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
NSData *data0 = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:#"images"]objectForKey:#"logo"]]];
UIImage *image = [UIImage imageWithData:data0];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
customCellClass.mainImage.image = image;
});
});
return customCellClass;
}
Besides, take a look at the difference between - (id)dequeueReusableCellWithIdentifier:(NSString *)identifier and - (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath.

Related

How to load more data in collectionviewcontroller

I had a little problem which is I can't properly reload a new data in collectionview whilst scrolling down at the bottom of collectionviewcontroller. The problem I had starting at this code if (indexPath.row == [selectedVideoData count] - 1). Below is my full code for collectionviewcontroller :
#import "PageVideosCVC.h"
#import "facebook.h"
#import "MBProgressHUD.h"
#import <AFNetworking/AFNetworking.h>
#import <AVFoundation/AVFoundation.h>
#import <SDWebImage/UIImageView+WebCache.h>
#interface PageVideosCVC () <UICollectionViewDataSource,UICollectionViewDelegate>
#end
#implementation PageVideosCVC
#synthesize selectedVideoData, selectNextVideoData;
static NSString * const reuseIdentifier = #"Cell";
-(void) viewWillAppear:(BOOL)animated {
UINavigationBar *navBar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
[UINavigationBar appearance].barTintColor = [UIColor lightGrayColor];
[self.view addSubview: navBar];
UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc] initWithTitle:#"< Back"
style:UIBarButtonItemStylePlain
target:self
action:#selector(backButtonTapped:)];
// UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithTitle:#"Done"
// style:UIBarButtonItemStyleBordered
// target:self action:nil];
NSString *selectedPageName = [[NSString alloc] initWithFormat:#"%#", self.pageName];
UINavigationItem *navItem = [[UINavigationItem alloc] initWithTitle:selectedPageName];
// navItem.rightBarButtonItem = doneItem;
navItem.leftBarButtonItem = cancelItem;
navBar.items = [NSArray arrayWithObjects: navItem,nil];
[UIBarButtonItem appearance].tintColor = [UIColor blueColor];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = NO;
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
facebook *fb = [[facebook alloc] init];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
NSDictionary *fbVideoParams = #{ #"fields": #"videos.limit(10){source,description,thumbnails.limit(1),length}"};
[fb fetchVideoInformationFromPages:fbVideoParams videoID:self.videoID completionHandler:^(NSDictionary *videoResult) {
if (videoResult != nil) {
selectedVideoData = [videoResult valueForKeyPath:#"videos.data"];
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
[MBProgressHUD hideHUDForView:self.view animated:YES];
});
}
}];
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = NO;
// Register cell classes
// [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
// Do any additional setup after loading the view.
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return selectedVideoData.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
// Configure the cell
// This is a last cell, I wanna load next video data from fb.
if (indexPath.row == [selectedVideoData count] - 1) {
NSString *fbToken = [facebook currentFBAccessToken];
NSString *fbNextVideoURL = [NSString stringWithFormat:#"https://graph.facebook.com/v2.5/606246146140197/videos?access_token=%#&pretty=0&fields=source,description,thumbnails.limit(1),length&limit=10&after=ODYxOTA5OTEzOTA3MTUx", fbToken];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[manager GET:fbNextVideoURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
selectNextVideoData = [responseObject valueForKey:#"data"];
NSLog(#"JSON Next Video: %#", selectNextVideoData);
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.view animated:YES];
// I had a problem setting the right thumbnail here.
UIImageView *imgView = (UIImageView *)[cell viewWithTag:100];
NSURL *thumbnailImage = [NSURL URLWithString:[selectNextVideoData valueForKeyPath:#"thumbnails.data"]];
// NSLog(#"JSON Next Video: %#", thumbnailImage);
[imgView sd_setImageWithURL:thumbnailImage placeholderImage:[UIImage imageNamed:#"placeholder.jpg"]];
[self.collectionView reloadData];
});
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
} else {
UIImageView *imgView = (UIImageView *)[cell viewWithTag:100];
NSURL *thumbnailImage = [NSURL URLWithString:[selectedVideoData valueForKeyPath:#"thumbnails.data.uri"][indexPath.row][0]];
[imgView sd_setImageWithURL:thumbnailImage placeholderImage:[UIImage imageNamed:#"placeholder.jpg"]];
}
return cell;
}
#pragma mark <UICollectionViewDelegate>
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
// NSLog(#"videos : %#", selectedVideoData);
// NSLog(#"videos source : %#", [selectedVideoData valueForKeyPath:#"source"][indexPath.row]);
NSURL *videoURL = [NSURL URLWithString:[selectedVideoData valueForKeyPath:#"source"][indexPath.row]];
self.playerController = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
[[self.playerController view] setFrame:[self.view bounds]]; // Frame must match parent view
[self.view addSubview:[self.playerController view]];
self.playerController.movieSourceType = MPMovieSourceTypeStreaming;
self.playerController.controlStyle = MPMovieControlStyleFullscreen;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doneButtonClick:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
[self.playerController play];
// Play the video using AVPlayer iOS9 above
// AVPlayer *player = [AVPlayer playerWithURL:videoURL];
// AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
// playerLayer.frame = self.view.bounds;
// [self.view.layer addSublayer:playerLayer];
// [player play];
}
-(void)doneButtonClick:(NSNotification*)aNotification{
NSNumber *reason = [aNotification.userInfo objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
if ([reason intValue] == MPMovieFinishReasonUserExited) {
// Your done button action here
// [self dismissViewControllerAnimated:YES completion:nil];
NSLog(#"done button tapped");
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerDidExitFullscreenNotification
object:nil];
[self.playerController stop];
[self.playerController.view removeFromSuperview];
}
}
- (IBAction)backButtonTapped:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
Perhaps rather than this approach you can try scrollView Delegate Methods :
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
CGPoint offset = aScrollView.contentOffset;
CGRect bounds = aScrollView.bounds;
CGSize size = aScrollView.contentSize;
UIEdgeInsets inset = aScrollView.contentInset;
float y = offset.y + bounds.size.height - inset.bottom;
float h = size.height;
// NSLog(#"offset: %f", offset.y);
// NSLog(#"content.height: %f", size.height);
// NSLog(#"bounds.height: %f", bounds.size.height);
// NSLog(#"inset.top: %f", inset.top);
// NSLog(#"inset.bottom: %f", inset.bottom);
// NSLog(#"pos: %f of %f", y, h);
float reload_distance = 10;
if(y > h + reload_distance) {
NSLog(#"load more rows");
}
}

Custom TableViewCells Not Being Reused

My chat application uses the following cellForRowAtIndexPath to setup the chat dialog history for the user:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
QBChatMessage *message = [[ChatService shared] messagsForDialogId:self.dialog.ID][indexPath.row];
if (message.attachments.count > 0) {
ImageTableViewCell *cell = [[ImageTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ImageCellIdentifier message:message];
[cell fillWithStickerMessage:message];
cell.backgroundColor = [UIColor whiteColor];
}
return cell;
}
Here is the init method in my ImageTableViewCell.m file.
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier message:(QBChatMessage *)message {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
NSData *imageData = [FTWCache objectForKey:[NSString stringWithFormat:#"%#", [message.attachments[0] valueForKey:#"ID"]]];
if (imageData) {
UIImage *image = [UIImage imageWithData:imageData];
[self.cellImage setImage:image];
} else {
for(QBChatAttachment *attachment in message.attachments){
// download file by ID
[QBRequest TDownloadFileWithBlobID:[attachment.ID integerValue] successBlock:^(QBResponse *response, NSData *fileData) {
[FTWCache setObject:fileData forKey:[NSString stringWithFormat:#"%#", attachment.ID]];
UIImage *image = [UIImage imageWithData:imageData];
[self.cellImage setImage:image];
} statusBlock:^(QBRequest *request, QBRequestStatus *status) {
// handle progress
} errorBlock:^(QBResponse *response) {
NSLog(#"error: %#", response.error);
}];
}
}
self.nameAndDateLabel = [[UILabel alloc] init];
self.timeLabel = [[UILabel alloc] init];
self.cellImage = [[UIImageView alloc] init];
self.cellImage.opaque = YES;
if ((IS_IPHONE_4) || (IS_IPHONE_5)){
[self.nameAndDateLabel setFrame:CGRectMake(20, 5, 300, 20)];
} else if (IS_IPHONE_6) {
[self.nameAndDateLabel setFrame:CGRectMake(20, 5, 355, 20)];
} else if (IS_IPHONE_6_PLUS) {
[self.nameAndDateLabel setFrame:CGRectMake(20, 5, 394, 20)];
}
[self.nameAndDateLabel setFont:[UIFont boldSystemFontOfSize:15]];
[self.nameAndDateLabel setTextColor:[UIColor lightGrayColor]];
[self.contentView addSubview:self.nameAndDateLabel];
self.backgroundImageView = [[UIImageView alloc] init];
[self.backgroundImageView setFrame:CGRectZero];
[self.backgroundImageView addSubview:self.cellImage];
[self.contentView addSubview:self.backgroundImageView];
}
return self;
}
The problem is that when scrolling through the table view, the cells are constantly initialized in initWithStyle in the ImageViewCell.m file. Shouldn't that only happen if the cell hasn't been created already? What am I doing wrong?
You're missing a call in cellForRowAtIndexPath to
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
forIndexPath:(NSIndexPath *)indexPath
or
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
depending on whether you registered your UITableViewCell nib or class.
So for example in cellForRowAtIndexPath you would do:
ImageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ImageCellIdentifier];
if (cell == nil) {
cell = [[ImageTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ImageCellIdentifier message:message];
}

UIImageView does not appear in custom UITableViewCell that is created dynamically

I am trying to integrate MSSlidingPanelController And I faced with problem. I want to have custom UITableViewCell that will contain image and text label.
I have TableViewItem inherited from UITableViewCell:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// Initialization code
self.textLabel.font = [UIFont fontWithName:FONT_OPENSANS_BOLD size:15];
[self.imageView addSubview:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"corners"]]];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.frame = CGRectMake(45.0f, 30.0f, 16.0f, 16.0f);
self.textLabel.frame = CGRectMake(70.0f, 40, 240.0f, 20);
}
+ (TableViewItem *) tableViewItemWithUncheckableName:(NSString *)name
withLeftsideImageFromUrl:(NSString *)url
{
TableViewItem *item;
NSParameterAssert(name);
item = [[TableViewItem alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:g_LMVCCellIdentifier];
[[item textLabel] setText:name];
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData * data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
if ( data != nil )
{
dispatch_async(dispatch_get_main_queue(), ^{
// WARNING: is the cell still using the same data by this point??
[[item imageView] setImage:[UIImage imageWithData: data]];
});
}
});
return (item);
}
Here how I use it:
- (TableViewSection *) fillingSectionUserInfo
{
TableViewItem *userInfoItem;
TableViewSection *section;
UserLogic * userLogic = [UserLogic instance];
NSString * userName = [NSString stringWithFormat:#"%# %#", [[userLogic currentUser] stringForKey:#"firstName"], [[userLogic currentUser]stringForKey:#"lastName"]];
userInfoItem = [TableViewItem tableViewItemWithUncheckableName:userName
withLeftsideImageFromUrl:[[userLogic currentUser] stringForKey:#"photo" ]];
[userInfoItem setActionWhenSelected:^(void){
}];
section = [TableViewSection tableViewSectionWitName:nil
selectionRule:SelectionRuleNone
andItems:userInfoItem, nil];
return section;
}
For each item I make setNeedsLayout in tableViewSectionWitName:selectionRule:andItems:

UITableView cellForRowAtIndexPath is not being called

I am having a problem with blank table data as this method is not getting called after I press search in my UISearchBar. I have tried everything and the table is just showing up blanking after pressing search.
This code takes the description from my json url and scans it for the searched word and then puts the index location of whatever description has that search term into an array (self.indexArray).
I would like to the call the table to only display those cells of the index values in that array.
- (void)viewDidLoad
{
[super viewDidLoad];
UISearchBar *tempSearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 64, 320, 40)];
self.searchBar = tempSearchBar;
self.searchBar.delegate = self;
self.searchBar.placeholder = #"Search listings...";
[self.view addSubview:self.searchBar];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
[self sendData];
}
- (void)sendData
{
NSString *search = self.searchBar.text;
NSString *temp = [NSString stringWithFormat:#"MY JSON RETRIEVAL LINK"];
NSURL *url = [[NSURL alloc] initWithString:temp];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]
initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation
, id responseObject) {
NSLog(#"%#",responseObject);
NSLog(#"%#",[responseObject class]);
self.images = responseObject;
self.descriptions = [[NSMutableArray alloc] init];
for (int i = 0; i < [self.images count]; i++)
{
[self.descriptions addObject:self.images[i][#"description"]];
}
for (int i = 0; i < [self.descriptions count]; i++)
{
NSLog(#"%d: %#", i, self.descriptions[i]);
if ([self.descriptions[i] rangeOfString:search options:NSCaseInsensitiveSearch].location != NSNotFound)
{
NSLog(#"ADDING, %d", i);
[self.indexArray addObject:[NSNumber numberWithInt:i]];
}
}
tableView = [[UITableView alloc] initWithFrame:CGRectMake(0,104,320,480) style:UITableViewStylePlain];
tableView.dataSource = self;
tableView.delegate = self;
[self.view addSubview:tableView];
[tableView reloadData];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#", error.localizedDescription);
}];
[operation start];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"FUNCTION CALLED");
TLCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if(cell == nil) {
cell = [[TLCustomCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
for(UIView *view in cell.contentView.subviews){
if ([view isKindOfClass:[UIView class]]) {
[view removeFromSuperview];
}
}
NSString *name = self.images[indexPath.row][#"name"];
NSString *location = self.images[indexPath.row][#"location"];
NSString *body = self.images[indexPath.row][#"description"];
NSString *list_type = self.images[indexPath.row][#"category"];
NSString *millisecs = self.images[indexPath.row][#"_createdAt"];
NSDate *date = [NSDate date];
NSTimeInterval ti = [date timeIntervalSince1970];
double myDouble = [millisecs doubleValue];
double delta = (ti * 1000) - myDouble;
NSString *time = [self calculateInterval:delta];
cell.nameLabel.text = name;
cell.locationLabel.text = location;
cell.bodyLabel.text = body;
CGFloat fixedWidth = cell.bodyLabel.frame.size.width;
CGSize newSize = [cell.bodyLabel sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = cell.bodyLabel.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
cell.bodyLabel.frame = newFrame;
cell.timeLabel.text = time;
if ([list_type isEqualToString:#"Sell"])
{
UIImageView *thumbnailView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"sell_icon_small.png"]];
thumbnailView.frame = CGRectMake(12, 12, 50., 50.);
[cell addSubview:thumbnailView];
}
else if ([list_type isEqualToString:#"Trade"])
{
UIImageView *thumbnailView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"trade_icon_small.png"]];
thumbnailView.frame = CGRectMake(12, 12, 50., 50.);
[cell addSubview:thumbnailView];
}
else if ([list_type isEqualToString:#"Wanted"])
{
UIImageView *thumbnailView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"want_icon_small.png"]];
thumbnailView.frame = CGRectMake(12, 12, 50., 50.);
[cell addSubview:thumbnailView];
}
else
{
UIImageView *thumbnailView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"ad_icon_small.png"]];
thumbnailView.frame = CGRectMake(12, 12, 50., 50.);
[cell addSubview:thumbnailView];
}
NSString *temp = self.images[indexPath.row][#"link"];
if ([temp isEqualToString:#"no_link"])
{
_thereIsAnImage = FALSE;
}
else
{
_thereIsAnImage = TRUE;
}
if (_thereIsAnImage)
{
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadWithURL:self.images[indexPath.row][#"link"]
options:0
progress:^(NSInteger receivedSize, NSInteger expectedSize)
{
// progression tracking code
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished)
{
if (image)
{
cell.imageView.image = image;
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
cell.imageView.clipsToBounds = YES;
cell.imageView.tag = indexPath.row;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleImageTap:)];
[tap setNumberOfTapsRequired:1];
[tap setNumberOfTouchesRequired:1];
[cell.imageView setUserInteractionEnabled:YES];
[cell.imageView addGestureRecognizer:tap];
}
}];
}
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.indexArray.count;
}
If you are doing it programmatically then you need to set tableview.delegate = self and tableview.datasource = self in viewDidLoad method. Put a breakpoint in numberOfRowsInSection: to see the number that it's returning to check whether it's more than zero or not.
I would ask that you please check your header file - it should include the following...
#interface YourTableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate>
Investigate how to implement UISearchBarDelegate and UISearchDisplayDelegate methods to manage search function in your (table) view controller. Read the Apple documentation UISearchBarDelegate and UISearchDisplayDelegate.
When you use a UISearchBar, you need a UISearchDisplayController to manage the search results.
If you are not using storyboards, it is important to set the appropriate data source and delegates for instances of both the UITableView and the UISearchDisplayController in your UITableViewController.
Then in your two table view data source methods, you need to provide information to the searchResultsTableView (accessed via self.searchDisplayController.searchResultsTableView) so that it knows how to prepare the search results table view.
For example...
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger nofRowsInSection = 0;
if (tableView == self.searchDisplayController.searchResultsTableView) {
nofRowsInSection = self.searchResults.count;
} else {
nofRowsInSection = self.indexArray.count;
}
return nofRowsInSection;
}
...and...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
... <<other code>> ...
NSString *name = nil;
NSString *location = nil;
etc...
if (tableView == self.searchDisplayController.searchResultsTableView) {
name = self.searchResults[indexPath.row][#"name"];
location = self.searchResults[indexPath.row][#"location"];
...etc...
} else {
name = self.images[indexPath.row][#"name"];
location = self.images[indexPath.row][#"location"];
...etc...
}
... <<other code>> ...
}
Note that self.searchResults should be an NSMutableArray and it should contain data for the search results table view, prepared by filtering self.indexArray based on the search bar text.
Hope this helps.
Your code seems OK . check whether table from storeybaord is connected with the table and delegated correctly.
Did you put
#interface YourViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
to the top of you ViewController.m file?
You need to set tableView.delegate = self and tableView.dataSource = self in the viewDidLoad

Scrolling is not proper When i used SDWebImage

I have this very serious problem of scrolling the table.
Initially i used GCD for loading the image in Background and setting on table cell.
but the table was not scrolling smoothly.
So i used SDWebImage for that but then the same thing is happening.
Could anyone let me know the reason for this. Why the table Scrolling is not smooth as expected.
Please let me know your views as my app is waiting its release for the only same purpose.
Code :
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *CellIdentifier = #"Cell";
customCellForExhibitor *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *xibPath = [[NSBundle mainBundle]loadNibNamed:#"customCellForExhibitor" owner:self options:nil];
for (id fileObject in xibPath)
{
cell = (customCellForExhibitor*)fileObject;
}
}
objDataModel = [parserDataContentArray objectAtIndex:indexPath.section];
cell.exhibitorNameLabel.text = [objDataModel exhibitorNameObjectClass];
cell.exhibitorText.text = [objDataModel exhibitorOfferObjectClass];
cell.exhibitorSponsorType.text = [objDataModel exhibitorSponsorTypeObjectClass];
[cell.exhibitorSponsorType setTextAlignment:NSTextAlignmentRight];
// #pragma mark GCD;
//
// NSString *ImageURL = [[parserDataContentArray objectAtIndex:indexPath.section] exhibitorImageObjectClass];
//// NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
//// cell.exhibitorImage.image = [UIImage imageWithData:imageData];
//
// dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// //this will start the image loading in bg
// dispatch_async(concurrentQueue, ^{
// NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
//
// //this will set the image when loading is finished
// dispatch_async(dispatch_get_main_queue(), ^{
//
// cell.exhibitorImage.image = [UIImage imageWithData:imageData];
// [cell setNeedsDisplay];
//
// });
// });
NSString *ImageURL = [[parserDataContentArray objectAtIndex:indexPath.section] exhibitorImageObjectClass];
[cell.exhibitorImage setImageWithURL:[NSURL URLWithString:ImageURL]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
if ([cell.exhibitorSponsorType.text isEqualToString:#"Gold"]) {
cell.exhibitorSponsorType.textColor = [UIColor colorWithRed:255/255.0 green:215/255.0 blue:0 alpha:1];
}
else if ([cell.exhibitorSponsorType.text isEqualToString:#"Silver"]){
cell.exhibitorSponsorType.textColor = [UIColor colorWithRed:192/255.0 green:192/255.0 blue:192/255.0 alpha:1];
}
else cell.exhibitorSponsorType.textColor = [UIColor colorWithRed:229/255.0 green:228/255.0 blue:226/255.0 alpha:1];
return cell;
}
Thank You
Best Regards.
Use lazy loading file instead here is the reference u can find it here along with demo how it is implemented.
https://stackoverflow.com/a/18032907/1305001
[cell addSubview:[self addViewWithURL:ImageURL NFrame:CGRectMake(0, 0, 50, 50)]];
add this method below cellForRow
-(UIView*)addViewWithURL:(NSString*)urlStr NFrame:(CGRect)rect
{
LazyLoad *lazyLoading;
lazyLoading = [[LazyLoad alloc] init];
[lazyLoading setBackgroundColor:[UIColor grayColor]];
[lazyLoading setFrame:rect];
[lazyLoading loadImageFromURL:[NSURL URLWithString:urlStr]];
return lazyLoading;
}
Set placeholder in LazyLoad.m file's init method as
-(id)init{
if (self==[super init]) {
[self setImage:[UIImage imageNamed:#"placeholder.png"]];
}
return self;
}
And change superClass of LazyLoad.h file to UIImageView from UIView as
#interface LazyLoad : UIImageView

Resources