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
{
}
Related
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 am opening a .xib file which contains one UITableView in my UIPopViewController and I have given datasource and delegate methods of UIATableView.
But after calling cellForRowAtIndexPath method my app get crashed.
My code is as follows:
- (IBAction)btnOilChangePressed:(id)sender {
OilChangeView *oilVC = [[OilChangeView alloc] initWithNibName:#"OilChangeView" bundle:nil];
UIPopoverController *popView = [[UIPopoverController alloc] initWithContentViewController:oilVC];
[popView setPopoverContentSize:CGSizeMake(480, 250)];
[popView presentPopoverFromRect:btnOilChange.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
following is the code on OilChangeView.m file
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [arrayInfo count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [arrayInfo objectAtIndex:indexPath.row];
NSLog(#"text:%#",[arrayInfo objectAtIndex:indexPath.row]);
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// Configure the cell...
return cell;
}
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.
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;
}
for some reason this UITableView keeps crashing and it seems like the UITableView is unable to display the secondsString for some reason but i have no idea why... please help me out here cause i have no idea what i could be doing wrong..... Thanks!!
#import "SettingsView.h"
#implementation SettingsView
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
transmissionSetup = [[TransmissionSetupViewController alloc] initWithNibName:#"TransmissionSetupViewController" bundle:nil];
transmissionSetup.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
NSLog(#"%i", [self getMinutes]);
[self setSeconds:10];
secondsString = [NSString stringWithFormat:#"%i", [self getSeconds]];
[self.tableView reloadData];
}
#pragma mark Table view methods
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
if (indexPath.section == 0) {
cell.textLabel.text = #"Every:";
cell.detailTextLabel.text = secondsString;
}
// Set up the cell...
return cell;
}
#end
You initialize your secondString with autoreleased string - so it is not guaranteed that it will be valid outside current scope. You need to retain it upon initialization (and don't forget to release later)
I would advise you to have a look at objective-c properties for accessing ivars.
// try this
- (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 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
if (indexPath.section == 0) {
cell.textLabel.text = #"Every:";
cell.detailTextLabel.text = secondsString;
}
// Set up the cell...
return cell;
}