i have a problem with willDisplayCell it doesn't stop fetch Xml from the url
my code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [itemsToDisplay count] + 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if (indexPath.row == [itemsToDisplay count]) {
cell.textLabel.text = #"Load More...";
} else {
MWFeedItem *item = [itemsToDisplay objectAtIndex:indexPath.row];
cell.textLabel.text = item.title;
}
return cell;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == [itemsToDisplay count]) {
// Parse
NSURL *feedURL = [NSURL URLWithString:#"http://gdata.youtube.com/feeds/api/users/RayWilliamJohnson/uploads?v=2&alt=rss&sort_field=added&start-index=21&max-results=20"];
feedParser = [[MWFeedParser alloc] initWithFeedURL:feedURL];
feedParser.delegate = self;
feedParser.feedParseType = ParseTypeFull; // Parse feed info and all items
feedParser.connectionType = ConnectionTypeAsynchronously;
[feedParser parse];
[self.tableView reloadData];
}
}
its look like he is in kind of loop that doesnt stop fetch xml
so how can i fix it so i will only called once?
tnx
The problem is that you have called reloadData within tableView:willDisplayCell:. reloadData will cause every UITableViewCell to get drawn again, means willDisplayCell will get called for every cell that will be visible on screen. Seems to me like you have an infinite loop there.
tableView:willDisplayCell: is definitely the wrong place to be doing that XML parsing. willDisplayCell should just be used to prepare the UI. I can't say for certain, but perhaps a better place to the XML parsing would be in your view controller's init method.
Related
I have a UITableView that displays checkmarks when a row is selected. The problem is that when the table view scrolls multiple checkmarks are shown when only one was ever row selected. The problem arises as the table scrolls and the dequeue process occurs. Here's my cellForRowAtIndexPath: method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MainCell"];
cell.selectedBackgroundView = [[UIView alloc] initWithFrame:CGRectZero];
cell.selectedBackgroundView.backgroundColor = [UIColor colorWithRed:204.0/255.0 green:56.0/255.0 blue:55.0/255.0 alpha:1];
}
// Get item from tableData
NSDictionary *item = (NSDictionary *)[displayItems objectAtIndex:indexPath.row];
cell.textLabel.text = [item objectForKey:#"key"];
[cell.textLabel setFont:[UIFont fontWithName: #"Asap-Bold" size: 14.0f]];
return cell;
}
and didSelect method:
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
selectedCityTableString = cell.textLabel.text;
cellAccessoryImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon-tick.png"]] ;
cellAccessoryNoneImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#""]] ;
if (cell.accessoryType==UITableViewCellAccessoryNone)
{
// cell.accessoryType=UITableViewCellAccessoryCheckmark;
cell.accessoryView = cellAccessoryImageView;
if (prev!=indexPath.row) {
cell=[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:prev inSection:0]];
//cell.accessoryType=UITableViewCellAccessoryNone;
cell.accessoryView = cellAccessoryNoneImageView;
prev=indexPath.row;
}
}
else{
// cell.accessoryType=UITableViewCellAccessoryNone;
cell.accessoryView = cellAccessoryNoneImageView;
}
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *mutCityStr = [[selectedCityTableString stringByReplacingOccurrencesOfString:#" " withString:#"+"] lowercaseString];
// NSString *mutCityStr = #"c";
[prefs setObject:mutCityStr forKey:#"selectedCityTableString"];
[prefs synchronize];
#ifdef DEBUG
NSLog(#"mutCityStr is %#",mutCityStr);
NSLog(#"selectedCityTableString is %#",selectedCityTableString);
NSLog(#"posting notification from TWO TABLES");
#endif
[[NSNotificationCenter defaultCenter] postNotificationName:#"TTSelectedList" object:selectedCountryTableString];
}
Supposing you have a property (attribute) called selectedRow use the combination of this methods:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if (indexPath.row == self.selectedRow) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// If there is a cell selected deselect
if (self.selectedRow != NSNotFound) {
NSIndexPath *previousIndexPath = [NSIndexPath indexPathForRow:self.selectedAQIType inSection:0];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:previousIndexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
}
// Select the touched cell
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
self.selectedRow = indexPath.row;
}
In your .h file
int selectedRow;
In your .m file
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// your other code for cell init,etc
int row = [indexPath row];
cell.accessoryType = (row == selectedRow) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
cell.textLabel.textColor= (row == selectedRow) ? [UIColor colorWithRed:242.0f/255.0f green:104.0f/255.0f blue:42.0f/255.0f alpha:1] : [UIColor blackColor] ;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedRow = [indexPath row];
[tableView reloadData];
}
Hope this helps!!!
UITableView's delegate method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath reuses the cell based on the reuseidentifier. Hence you need to reset the entire cell contents to default.
In your case uncheck the cell's view before you return the cell.
To solve this problem, store your selected row indexes in one NSArray. (in didSelectRowAtIndexPath method)
And in cellForRowAtIndexPath method, check whether indexPath.row is available in that array then enable your checkmark, else disable.
Note: Maintain array for check-uncheck event
Hope this will help you.
In my app, You can tap a cell, and it brings up a new view. You can edit the tableviewCell's textLabel, and save it. But when you switch views and come back to the tableView, the cells are in a different order. What could be the reason for this?
Here is my Code:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString * identifier = #"identifier";
self.cell = [tableView dequeueReusableCellWithIdentifier:identifier];
h = [self.tableArray objectAtIndex:indexPath.row];
NSString *brandModel = [[h.brand stringByAppendingString:#" "] stringByAppendingString:h.model];
self.cell.mainLabel.text = brandModel;
self.cell.nicknameLabel.text = handguns.nickname;
return self.cell;
}
If you are reloading tableView after saving UITableView cell then It will be reordered as initial because array from which you are setting cell data is as it is.You can change only table View cells not array data position in an array.
Below I have written a UITableView code to move cells and it is working fine after pushing view.If I remove reload method from viewWillAppear:
#import "MoveCellViewController.h"
#interface MoveCellViewController ()
#end
#implementation MoveCellViewController
- (void)viewDidLoad
{
UIBarButtonItem *left=[[UIBarButtonItem alloc] initWithTitle:#"Edit" style:UIBarButtonItemStyleBordered target:self action:#selector(edit)];
self.navigationItem.leftBarButtonItem=left;
myArray=[[NSMutableArray alloc]init]; //mutable array;
myArray=[NSMutableArray arrayWithObjects:#"Aman",#"Ankit",#"Sumit",#"Hercules",#"Jackie Chan", nil];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)edit
{
if (self.navigationItem.leftBarButtonItem.title==#"Edit") {
self.navigationItem.leftBarButtonItem.title=#"Done";
[_tableView setEditing:YES];
}else
{
[_tableView setEditing:NO];
self.navigationItem.leftBarButtonItem.title=#"Edit";
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [myArray count];
}
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier=#"cellIdentifier";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell==nil) {
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.userInteractionEnabled=YES;
cell.textLabel.text=[myArray objectAtIndex:indexPath.row];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellEditingStyleNone;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
id ob = [myArray objectAtIndex:destinationIndexPath.row];
[myArray replaceObjectAtIndex:destinationIndexPath.row withObject:[myArray objectAtIndex:sourceIndexPath.row]];
[myArray replaceObjectAtIndex:sourceIndexPath.row withObject:ob];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NextViewController *nx=[[NextViewController alloc] init];
[self.navigationController pushViewController:nx animated:YES];
}
#end
This is working code and will not change after push view controller.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *CellIdentifier = [NSString stringWithFormat:#"S%1dR%1d",indexPath.section,indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
h = [self.tableArray objectAtIndex:indexPath.row];
NSString *brandModel = [[h.brand stringByAppendingString:#" "] stringByAppendingString:h.model];
self.cell.mainLabel.text = brandModel;
self.cell.nicknameLabel.text = handguns.nickname;
return self.cell;
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:nil];
}
Write rest of the code here
}
I have a simple UITableView with 9 cells. When I move the table up or down by scrolling, I get EXE bad access. NSZombieMode points at the cellForRowAtIndexMethod.
- (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];
}
cell.textLabel.text = [lineArray objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
Can anyone suggest what is wrong ?
If ARC is disabled then add autorelease when you create cell
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
This can be the reason of the leaks. Check also lineArray since it used like ivar and probably this array was released at some point.
My guess is you're trying to access an element in your lineArray that is out of bounds.
IE: indexPath.row is returning a 6 when you only have 3 elements in your lineArray.
It's occurring when you scroll down as it triggers cellForRowAtIndexPath to be called on higher number rows (rows that with indexPath.row > 3 for example)
I'll go one more step and guess that you're probably statically returning numberOfRowsForSection.
Setting it to lineArray.count should fix it.
According to my understanding :-
1) in the lineArray you have some 9 items but in the numberOfRowsInSection you are returning the rowCount more than the items in the array and so it crashes and points to ceelForRowAtIndex.
2) Here is the sample code for your understanding :-
- (void)viewDidLoad
{
[super viewDidLoad];
lineArray = [[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"5", nil];
tableView1 = [[UITableView alloc]init];
tableView1.delegate = self;
tableView1.dataSource = self;
tableView1 .frame =self.view.frame;
[self.view addSubview:tableView1];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [lineArray count];
//return ;
}
- (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];
}
cell.textLabel.text = [lineArray objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
I have a button that when pressed, a tableview section will be added and will also add a new row to that section. How can I implement this programatically?
I have an array of cells.
Here are my codes
- (IBAction)addCell:(id)sender {
UITableViewCell *newCell = [[UITableViewCell alloc] init];
counter++;
[cells addObject:newCell];
[self.tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [cells count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//this is where i want to adjust the row per section
//this code hide the recent sections, only the current created section appears
return [cells objectAtIndex:indexPath.row];
}
Hi try reading this:
How to display the UITableView programmatically?
Adding cells programmatically to UITableView
Hope this could help you.
First, update your's datamodel(NSArray or mutable). Second, when you want tableview refresh, add a code [self.tableView reloadData];
oops, your code some strange uitaleviewDataSource, Delegate Method.
also, your have a some mistake.
why you implements numberOfRowsInSection return 1? very strange.
I apprecated below code.
CASE 1. No has DataModel.
- (IBAction)addCell:(id)sender
{
cellRowsCount++;
[self.tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return cellRowsCount;
}
- (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];
}
return cell;
}
your codes, dataModel(NSArray or mutable) does not necessarily need, so I simply rowCount variable added and your rowsCount of tableviewCell has synchronized.
If you wanna with DataModel, below CASE2. refer plz.
CASE2. has DataModel.
- (IBAction)addCell:(id)sender
{
textCount ++;
NSString *cellText = [NSString stringWithFormat:"blah %d", textCount];
[myArray addObject:cellText];
[self.tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [myArray count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[myArray objectAtIndex:section] 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];
}
cell.textLabel.text = (NSString *)[myArray objectAtIndex:indexPath.row];
return cell;
}
You only have to add the new section and the new item to the array that holds the section and the items like so:
- (void)viewDidLoad
{
[super viewDidLoad];
animals = #{#"Section 1" : #[#"Item 1", #"Item 2", #"Item 3"],
#"Section 2" : #[#"Item 1", #"Item 2"]};
}
after that you just reload the tableView wherever your logic needs:
[self.tableView reloadData];
im learning Obj-C and im treating to make my first UITableView with "Hello world" text.
My problem is i can't show on screen right edit button. this is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[[cell textLabel] setTextAlignment:(UITextAlignmentCenter)];
cell.textLabel.text=#"Hello World";
//[cell.textLabel setText:#"Hola2"];
return cell;
}
and:
- (void)viewDidUnload
{
[super viewDidUnload];
self.navigationItem.rightBarButtonItem=self.editButtonItem;
}
Am I missing something?
Thanks for help.
self.navigationItem.rightBarButtonItem=self.editButtonItem;
This must go in the viewDidLoad
are you also setting the rows and sections correct?
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 1;
}