Custom UITableView not refreshing cells - objective-c

I am creating a custom UITableViewCells. I am using a NIB file as the cell. Its displaying some data from REST API's. The problem I am having is when I scroll down & then back up, the cells are not refreshed. It shows the data from when I scrolled down. Here's my code -
MyViewController.h
#interface FLOViewController : UIViewController <UISearchBarDelegate,
UITableViewDelegate,
UITableViewDataSource>
{
UISearchBar *sBar;
UITableView *searchResTable;
NSArray *searchRes;
UITableViewCell *resultsOne;
}
#property (nonatomic, retain) IBOutlet UILabel *photos;
#property(nonatomic, retain) IBOutlet UITableView *searchResTable;
#property (nonatomic, retain) NSArray *searchRes;
/* Search Results Templates */
#property (nonatomic, assign) IBOutlet UITableViewCell *resultsOne;
MyViewController.m
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(self.searchRes == nil)
return nil;
static NSString *cId = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cId];
if(cell == nil)
{
NSLog(#"CREATING NEW CELL");
[[NSBundle mainBundle] loadNibNamed:#"ResultsOne" owner:self options:nil];
cell = self.resultsOne;
self.resultsOne = nil;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
//from here on displaying images etc from REST API.
UIImageView *uPhoto = (UIImageView *)[cell viewWithTag:2];
NSString *photoURL = [[self.searchRes objectAtIndex:[indexPath row]] objectForKey:#"originator_photo_url"];
if(photoURL)
{
[UIView beginAnimations:#"fadeIn" context:NULL];
[UIView setAnimationDuration:0.5];
NSString *urlString = [NSString stringWithString:photoURL];
[uPhoto setImageWithURL:[NSURL URLWithString:urlString]
placeholderImage:[UIImage imageNamed:[NSString stringWithFormat:#"ph%d.png",[indexPath row]]]];
[UIView commitAnimations];
}
//similarly display other sections in the cell...
Why are the contents of my cell not refreshing? Even when I put in completely new data (through search from REST API's) some of the cells still show old views in the tablecells.
UPDATE: If I comment out UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cId]; then the problem is solved. i.e. I dont see repetition of cell content on scrolling.
Because I am creating custom ImageViews in UITableViewCell do i need to do something special to clear out the cell content before new content can be added??

To me it looks like you forgot to reset the uPhoto-UIImageView, in case the photoURL is nil. This brings in cached data.
if (photoURL) {
...
}
else {
uPhoto.image = nil;
}

You are using
static NSString *cId = #"Cell";
Let's try different identifier for each cell. I face this problem and solve it by using different cell identifier like
static NSString *cId =[NSString StringWithFormat : #"Cell_%d_%d",[indexPath section], [indexPath row] ];
I think it may solve your problem.

Related

Null data when loading DetailView

I have UITableView I want to click on row and load detail view but I have null information in my Log in detail view
would you please help m win this implementation
Thanks in advance!
cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath
{
//Load Cell for reuse
static NSString *CellIdentifier = #"TestCell";
TestCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell =[ [[NSBundle mainBundle] loadNibNamed:#"TestCell" owner:nil options:nil]
lastObject];
}
_tests = [server info];
_t = [NSMutableString stringWithFormat:#"%# ", [_tests objectAtIndex:indexPath.row]];
NSString *testdata = _t;
_components = [testdata componentsSeparatedByString:#","];
for (NSString *aComponent in _components) {
if ([aComponent hasPrefix:#"titletest"]) {
_subComponents = [aComponent componentsSeparatedByString:#":"];
_testString = [_subComponents[1] stringByTrimmingCharactersInSet:[NSCharacterSet
characterSetWithCharactersInString:#"\""]];
}if ([aComponent hasPrefix:#"note"]){
_subComponents = [aComponent componentsSeparatedByString:#":"];
_noteString = [_subComponents[1] stringByTrimmingCharactersInSet:[NSCharacterSet
characterSetWithCharactersInString:#"\""]];
break;
}
}
cell.title.text = _testString;
cell.note.text = _noteString;
return cell;
}
didSelectRowAtIndexPath method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
TestDetailView *c = [[TestDetailView alloc] init];
///I don't know what should I put here to c
[self.navigationController pushViewController:c animated:YES];
}
but in My detail view
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:YES];
NSLog(#" test : %#",_Info.datas); ==>> my log was (null)
}
My Detail View Header
#property (strong, nonatomic) IBOutlet UILabel *bDetailTitle;
#property (strong, nonatomic) IBOutlet UILabel *bDetailNote;
#property (nonatomic, strong) NSArray *datas;
#property (nonatomic,strong) TestTable *Info;
#end
I'm assuming that TestDetailView is a ViewController subclass and that you have a property on it possibly called datas. If that is the case you appear to create your detail view controller in didSelectRowAtIndexPath: like this:
TestDetailView *c = [[TestDetailView alloc] init];
But then immediately change it the pointer to something else (possibly nil):
c = [_datas objectAtIndex:indexPath.row];
objectAtIndex returns an id which means your code probably doesn't throw a warning in Xcode, but at run time if [_datas objectAtIndex:indexPath.row] does not return a UIViewController (and I suspect that it does not) your app could crash. If it is not throwing an error or crashing you possibly have another problem in that _datas is nil in your parent view controller.
It is a very common technique to pass values to view controllers I would recommend reading up on how to do this. This type of question has been asked on S.O. many times:
How to set value for NSString in another view controller from one viewcontroller

Custom TableView-Cell (Data from server) select multiple values with accessory change

I am working with TableView and wanted Custom TableViewCell to have a Small Image, Name and one custom image (With Tickmark and without Tick) can be on accessory to show if Cell is selected and if it's not selected it will show without Tick image on unselected cells.
And if i want to select multiple cells then it should show Tick image on selected Cells and Untick image on unselected cells and after that when i click on a button then i should be able to get the selected cell id's.
On the tableView i am getting all the values from the server and images also from URL's but the Tickmark and Unselected Tick mark image will be used the project itself.
So far i have created :
Class .h,.m,.xib of "ResultTableCell" of type UITableViewCell and my Main view "Result" with the TableView and a Button on top (on click of button i'll get the values of selected cells)
ResultTableCell.h
#import <UIKit/UIKit.h>
#interface ResultTableCell : UITableViewCell
#property (nonatomic, retain) IBOutlet UILabel *nameLabel;
#property (nonatomic, retain) IBOutlet UIImageView *thumbImageView;
ResultTableCell.m
#import "ResultTableCell.h"
#implementation ResultTableCell
#synthesize nameLabel,thumbImageView;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
ResultTableCell.xib
The right hand side image on the xib is the place where the accessor image will come.
ResultTableCell.xib
And the main xib
Result.h
#import <UIKit/UIKit.h>
#import "ASIFormDataRequest.h"
#interface Results : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
NSMutableArray *nameData;
}
#property (nonatomic, retain)NSMutableArray *nameData;
#property (nonatomic, retain)NSMutableArray *ImageData;
#property (nonatomic, retain)NSMutableArray *idData;
#property (nonatomic, retain)UITableView *table;
#property (nonatomic, retain) IBOutlet UIButton *done;
#property (nonatomic, retain) NSMutableArray *arFors;
-(IBAction)save_done:(id)sender;
Result.m
#import "Results.h"
#import "ResultTableCell.h"
#interface Results ()
#end
#implementation Results
#synthesize arFors;
#synthesize done,nameData,table,addressData,ImageData,idData;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.arFors=[NSMutableArray array];
// I am Getting Name,id and image url data from my HomeViewController
NSLog(#"Name Data from home view is %#",nameData); // 10 Names get's printed in log
NSLog(#"id Data is %#",idData);
NSLog(#"URL image data is %#",ImageData);
table = [[UITableView alloc]initWithFrame:CGRectMake(0, 221, 320, 327) style:UITableViewStylePlain];
table.delegate = self;
table.dataSource = self;
[self.view addSubview:table];
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"Name data count is %d",nameData.count);
return nameData.count;
//return 10;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/* UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:#"MainCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MainCell"];
}*/
static NSString *simpleTableIdentifier = #"ResultTableCell";
ResultTableCell *cell = (ResultTableCell *)[table dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ResultTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if ([self.arFors containsObject:[NSNumber numberWithInt:indexPath.row]]) {
cell.accessoryView = [[ UIImageView alloc ]
initWithImage:[UIImage imageNamed:#"table_tick" ]];
}
else {
cell.accessoryView = [[ UIImageView alloc ]
initWithImage:[UIImage imageNamed:#"table_add" ]];
}
NSLog(#"data is ************* %#",nameData);
cell.nameLabel.text = [nameData objectAtIndex:indexPath.row];
NSURL * imageURL = [NSURL URLWithString:[ImageData objectAtIndex:indexPath.row]];
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage * image2 = [UIImage imageWithData:imageData];
cell.ImageView.image = image2;
cell.ImageView.contentMode = UIViewContentModeScaleAspectFit;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"didSelectRowAtIndexPath %d",indexPath.row);
if ([self.arFors containsObject:[NSNumber numberWithInt:indexPath.row]]) {
[self.arFors removeObject:[NSNumber numberWithInt:indexPath.row]];
}
else{
[self.arFors addObject:[NSNumber numberWithInt:indexPath.row]];
// [self.table cellForRowAtIndexPath:indexPath];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView reloadData];
}
-(IBAction)save_done:(id)sender
{
NSLog(#"selected cell values are %#",self.arFors);
}
Now with this code everything is working fine (tick image is shown on selected cells and untick image on unslected cells and on clicking the Done button i am getting the selected cell values),
But the Problem comes when i tapp on a cell then it like hangs and takes 5-6 seconds of time to change accessor image as it fires [tableView reloadData] in didselectrowatindexpath method so all data reloads again in the tableview and then the accessor image changes, please can any one correct my code or enhance it so that it works fast.
I have tried a lot of ways but i was not able to do it without the reloading of table and if i reload table it takes long time.
Coding help will be much tankful.
Your problem is:
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
Because it downloads all of the image data from the network each time you reload the table view. You should be doing this asynchronously and caching the returned image so you don't need to download it repeatedly. Take a look at a library like SDWebImage to help you with this.

didSelectRowAtIndexPath really doesn't work

The didSelectRowAtIndexPath not working.
Have I configured the 2 delegates. Everything is linked (tableview, tableviewcell).
Already deleted and did it again.
I searched for everything here and nothing worked.
I think this was one of the best link, still to no avail.
My last hope is that it is, I'm opening my ViewController, where has this tableview, for modal. But it would be VERY wrong the problem.
Other than that, I need some help
Somo codes .H
#interface simulator : UIViewController <UITableViewDelegate, UITableViewDataSource, UIScrollViewDelegate>
{
NSArray *array_products;
}
#property (nonatomic, strong) NSDictionary *plist_products;
#property (nonatomic, strong) IBOutlet UITableView *table_menu_left;
#property (nonatomic, strong) NSString *file_plist;
#end
Some codes .M
#import "cel_products.h"
- (void)viewDidLoad
{
NSString *path_root = [[NSBundle mainBundle] bundlePath];
NSString *full_path = [path_root stringByAppendingPathComponent:self.file_plist];
self.plist_products = [[NSDictionary alloc] initWithContentsOfFile:full_path];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"id_cell_products";
UITableViewCell *cell = [self.table_menu_left dequeueReusableCellWithIdentifier:CellIdentifier];
array_products = [self.plist_produtcs allKeys];
if (cell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"cel_products" owner:self options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[cel_products class]])
{
cell = (cel_products *)currentObject;
break;
}
}
}
cell.textLabel.text = [array_products objectAtIndex:indexPath.row];
return cell;
}
// numberofrowsinsection - OK
// numberofsectionintableviw - OK
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Hein?????");
// Nothing..........
}
I humbly thousand apologies to all!
I inadvertently clicked Attributes Inspector> Selection: NO SELECTION
So I do not find anything in the code.
Again, I apologize to everyone, but if someone, are having this problem, this is one more step to be verified. " Change to Attributes Inspector> Selection: SINGLE SELECTION or MULTIPLE SELECTION ( is up to you )
Thanks all for the answers and help
Did you set a break at didSelectRowAtIndexPath? Try and see if it breaks successfully there.
Expanding on rokjark's answer you have to manually set the delegate and data source to the file in question.
Your header file simulator.h simply declares it as A delegate/data source for SOME UITableView.
You still need to point table_menu_left to use simulator.h as THE delegate file to handle all of it's callbacks.
Set:
self.table_menu_left.delegate = self;
self.table_menu_left.datasource = self;
And again set a break in didSelectRowAtIndexPath and see if it gets called.

Unable to get UIImage to fit custom UITableViewCell

Hi guys I'm unable to make the image file the custom uitableview cell i made. The image is so small and i don't know how to enlarge it. Thnx in advance for the help.
#import <UIKit/UIKit.h>
#interface customCell : UITableViewCell
{
//UILabel *frontLabel;
}
#property(nonatomic , strong) IBOutlet UILabel *label;
#property(nonatomic , strong) IBOutlet UILabel *label2;
#property(nonatomic , strong) IBOutlet UIImageView *imgView;
#end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"cell";
customCell * cell =[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[customCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
User * user = [self.list objectAtIndex: indexPath.row];
cell.label.text = user.username;
NSString *url = user.profilePic;
UIImage * image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url]]];
cell.imageView.contentMode =UIViewContentModeScaleAspectFit;
cell.imageView.image =image;
return cell;
}
In your customCell class (btw all classes should start with a capital letter, properties and variables should be lowercase), you just need to set the frame property of your imageView object to the correct size and position you want.
Something like imageView.frame = CGRectMake(10., 10., 50., 50.) where the first two parameters are the x and y position of the top right corner of the image view, and the second two parameters are the width and height.
Or, since you have those properties specified as IBOutlet's, if you're using a XIB file for the layout, you should have the size setup already in there.
Without seeing a screenshot of Interface Builder for the XIB or the implementation code for customCell, that's the best I can help.

UITableView/UITabBarController: trying to figure out a method to pass a variable to my destination controller when a row is selected

I am using a UITableView that points to a UITabBarController to display a series of UIWebViews within these tabs.
I would like define a string to be used to construct a URL for each tab based on the item selected. The issue I am facing is how to pass the URL to the StateTrendViewController controller.
StateTableViewController.h
#import <UIKit/UIKit.h>
#interface StateTableViewController : UITableViewController
{
NSArray *StateList;
}
#property (nonatomic, retain) NSArray *StateList;
- (void) buildStateList;
#end
StateTableViewController.m
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [StateList count];
}
- (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];
}
NSInteger rowNumber = indexPath.row;
NSString *stateName = [StateList objectAtIndex:rowNumber];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = stateName.capitalizedString;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSInteger rowNumber = indexPath.row;
NSString *stateName = [StateList objectAtIndex:rowNumber];
[[self.navigationController.viewControllers objectAtIndex:2] setTitle:stateName.capitalizedString];
}
StateTrendViewController.h
#import <UIKit/UIKit.h>
#interface StateTrendViewController : UIViewController
{
IBOutlet UIWebView *StateTrendView;
IBOutlet NSString *ViewURL;
}
#property (nonatomic, retain) UIWebView *StateTrendView;
#property (nonatomic, retain) NSString *ViewURL;
#end
StateTrendViewController.m
#import "StateTrendViewController.h"
#implementation StateTrendViewController
#synthesize StateTrendView;
#synthesize ViewURL;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void) viewWillAppear:(BOOL)animated
{
NSString *baseURL = #"https://www.google.com/search?q=";
NSString *state = #"test";
NSString *fullURL = [baseURL stringByAppendingString:state];
NSURL *url = [NSURL URLWithString:fullURL];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url]; [StateTrendView loadRequest:requestObj];
}
I need to replace the static setting with the sting passed to the controller using the ViewURL property I have setup:
NSString *state = #"test";
I am using a Storyboard in my project in Xcode 4.2.1. How should I go about passing that string value to my controller?
You override prepareForSegue, more detail is here
If all you are passing is a string, the simplest way might be to define a property on your the view controller you are presenting to hold the string. I notice you already have one, *ViewURL defined, but I'm not sure if that's what you've setup for this specific task or if that is already intended for something else.
Based on the code you've shared, I'm assuming that in your didSelectRowAtIndexPath in your table controller, the controller you are setting the title, and presumably later pushing, is an instance of a StateViewController:
[[self.navigationController.viewControllers objectAtIndex:2] setTitle:stateName.capitalizedString];
If this line does indeed reference an instance of StateTrendViewController, you would assign your string in the same way you're assigning title. This needs to be set before you segue into the new view controller (I don't see that code):
[[self.navigationController.viewControllers objectAtIndex:2] setViewURL:#"MyPassedString"] //assign custom property
When your view controller appears on screen, it will have it's property ViewURL already set.
Also note that your naming style for instance variables is not a standard cocoa convention, ivars beginLowerCase. Additionally, it is unusual and may not work to push a TabBar controller inside an existing nav controller, presumably from table view view controller inside an existing nav controller. Typically a TabBar is considered a top-level navigational construct, and you may wish to rethink your architecture accordingly.