I am getting a crash (app quits in iOS simulator) when I click on a cell. The error code is
"EXC_BAD_ACCESS (code = 1, address= 0x310cc493)
Here is the code:
// .h
#import <UIKit/UIKit.h>
#interface ChecklistsViewController : UITableViewController
#end
// .m
#import "ChecklistsViewController.h"
#interface ChecklistsViewController ()
#end
#implementation ChecklistsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ChecklistItem"];
UILabel *label = (UILabel *)[cell viewWithTag:1000];
if (indexPath.row % 5 == 0) {
label.text = #"Walk the dog";
} else if (indexPath.row % 5 == 1) {
label.text = #"Brush my teeth";
} else if (indexPath.row % 5 == 2) {
label.text = #"Learn iOS development";
} else if (indexPath.row % 5 == 3) {
label.text = #"Soccer practice";
} else if (indexPath.row % 5 == 4)
label.text = #"Eat ice cream";
return cell;
}
- tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
} // Control reaches end of non-function
#end
In your example you do not allocate a UITableViewCell if none was dequeued. You need to do something like this:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ChecklistItem"];
if( cell == nil ) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"ChecklistItem"] autorelease];
// whatever additional initialization
...
}
You need to allocate the UITableViewCell in tableView: cellForRowAtIndexPath: method.
Your method should be like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UItableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UItableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//INSERT YOUR CODE
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UItableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UItableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//write your code here
return cell;
}
Related
I have a tableview called AdminOrderViewController and it has customcell called StepperProgressCell.
This customcell has a custom UIView called AYStepperView. There is a button in this UIView and I implemented a delegate on it, whenever it gets clicked and I clicked method is getting called on AdminOrderViewController.
However, I could not able to figure out how to pass clicked header cell.section to AYStepperView ??
AdminOrderViewController.m
#interface AdminOrderViewController : UIViewController <AYStepperViewDelegate>
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"StepperProgressCell";
StepperProgressTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (!cell) {
cell = [[StepperProgressTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.stepperView.delegate= self;
return cell;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
AdminHeaderFooterView *sectionHeaderView = [self.adminTableView dequeueReusableHeaderFooterViewWithIdentifier:SectionHeaderViewIdentifier];
if (sectionHeaderView == nil)
{
sectionHeaderView = [[AdminHeaderFooterView alloc] initWithReuseIdentifier:SectionHeaderViewIdentifier];
}
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(selectHeaderAction:)];
[sectionHeaderView addGestureRecognizer:tapGesture];
return sectionHeaderView;
}
-(void) selectHeaderAction :(UITapGestureRecognizer*) gestureRecognizer
{
AdminHeaderFooterView* cell = (AdminHeaderFooterView*)gestureRecognizer.view;
[self toggleSection:cell withSection: cell.section];
// how to pass clicked section to AYStepperView??
}
-(void)clicked :(NSUInteger) currentSection
{
NSLog(#"Stepper clicked %lu", currentSection);
}
StepperProgressTableViewCell.m
#implementation StepperProgressTableViewCell
#synthesize stepperView;
- (void)awakeFromNib {
[super awakeFromNib];
[self setUpViews];
}
- (void)setUpViews {
self.stepperView = [[AYStepperView alloc]initWithFrame:CGRectMake(0, 0 , [[UIScreen mainScreen] bounds].size.width, kFormStepperViewHeight) titles:#[#"Processing",#"Ready",#"Delivered", nil)]];
[self addSubview:self.stepperView];
}
AYStepperView.h
#property (nonatomic) NSUInteger currentSection;
AYStepperView.m
#protocol AYStepperViewDelegate <NSObject>
#required
- (void)clicked :(NSUInteger) currentSection;
#end
- (void)buttonPressed:(UIButton *)sender {
[stepperDelegate clicked : currentSection];
}
The cell should not need to know which row or section it is in; Your table view controller can find this easily, given a reference to the cell.
Your view controller should not set itself as the delegate of the stepper view. It should be a delegate of the cell. The cell should be the delegate of the stepper view. This is a bit more complicated but it maintains better separation of concerns and makes the whole thing cleaner.
AYStepperView.h
#protocol AYStepperViewDelegate <NSObject>
#required
- (void)clicked;
#end
AYStepperView.m
- (void)buttonPressed:(UIButton *)sender {
[stepperDelegate clicked];
}
StepperProgressTableViewCell.h
#protocol StepperProgressTableViewCellDelegate <NSObject>
#required
- stepperChanged: (StepperProgressTableViewCell) cell;
StepperProgressTableViewCell.m
-(void)awakeFromNib {
self.stepperView.delegate= self;
}
- (void)clicked {
[self.delegate stepperChanged: self];
}
AdminOrderViewController.m
#interface AdminOrderViewController : UIViewController <StepperProgressTableViewCellDelegate>
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"StepperProgressCell";
StepperProgressTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (!cell) {
cell = [[StepperProgressTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.delegate= self;
return cell;
}
-(void)stepperChanged:(StepperProgressTableViewCell)cell {
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// Now do something with indexPath.section
}
in cellForRowAtIndexPath set section to stepper view
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"StepperProgressCell";
StepperProgressTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (!cell) {
cell = [[StepperProgressTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.stepperView.delegate= self;
cell.stepperView.currentSection = indexPath.section;//set section value
return cell;
}
I'm loading a tableview and would like to grey out object 2 and objet 4 and make them disabled to user interaction.
In .h I have
#property (nonatomic, strong) NSArray *list;
and .m:
- (void)viewDidLoad
{
[super viewDidLoad];
self.list = [[NSArray alloc] initWithObjects:#"Object 1", #"Object 2", #"Object 3", #"Object 4", #"Object 5", nil];
}
and
- (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 = [list objectAtIndex:[indexPath row]];
return cell;
}
I've tried getting the object using
object = [self.list objectAtIndex: 2] to get Object 2 but it doesn't do anything.
How do I go about doing this?
Is textLabel a UILabel or a UITextField? The naming leaves me to wonder. Assuming it's a UILabel and you want to prevent interaction with the cell (and controls in it) you could do the following.
- (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 = [list objectAtIndex:[indexPath row]];
if (indexPath.row == 1 || indexPath.row == 3) {
cell.userInteractionEnabled = NO;
} else {
cell.userInteractionEnable = YES;
}
return cell;
}
Or are you just trying to prevent users from selecting the cell? In which case you should probably consider overriding tableView:willSelectRowAtIndexPath: in the UITableViewDelegate.
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 1 || indexPath.row == 3) {
return nil;
return indexPath;
}
i'm trying to do a selection list in UITableView but whenever i tap in a row, two row are marked. For example if i tap the first row it adds a checkmark to row = 0 and row = 11. I think the problem is caused by reuse of cells but i don't understand how solve it.
I attach my code .h:
#interface tabellaViewController : UITableViewController
#property (nonatomic, strong) NSArray *listaingredienti;
#end
and my code .m:
- (void)viewDidLoad
{
[super viewDidLoad];
_listaingredienti = [NSArray arrayWithObjects:#"formaggio", #"crudo", #"pomodorini", #"fossa", #"bresaola", #"funghi", #"salame", #"fontina", #"rucola", #"radicchio", #"peperoni", #"ciccioli", #"squacquerone", #"gorgonzola", #"salsiccia", #"cipolla", #"feta", #"acciughe", #"pecorino", nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_listaingredienti count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [_listaingredienti objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow]
animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
I've seen UITableView didSelectRowAtIndexPath add additional checkmark at tap where there is a similar post but i already use dequeueReusableCellWithIdentifier:CellIdentifier.
Anyone can help me?
Ok,
i'm just solved my question. Actually, the problem was in reuse of cells, but this code fix it.
Just replace in cellForRowAtIndexPath::
static NSString *CellIdentifier = #"Cell";
with:
NSString *CellIdentifier = [NSString stringWithFormat:#"MyReuseIdentifier %d",indexPath.row];
When I build and run there is nothing displayed. No text just empty cells.
Here is my code:
#import "plungerselection.h"
#implementation plungerselection
#synthesize tableData;
-(void) viewDidLoad
{
tableData = [[NSArray alloc] initWithObjects:#"Turbo", #"Hollow Turbo", #"Single Pad", #"Dual Pad", #"Bullet", nil];
[super viewDidLoad];
}
#pragma mark - TableView Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;{
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyCell"];
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
}
return cell;
}
#end
Make sure you have wired up the datasource and delegate connections in Interface Builder.
You are only setting the text in the cell if dequeueReusableCellWithIdentifier: returns nil which in this case doesn't happen (and even if it did it will only happen a few times before all the cells that are needed get in the queue). You should set the text outside of the if (cell == nil)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyCell"];
}
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
i've a simple View that is the third level of a UINavigationController, it show an empty table from a nib, here is the code of the .m file:
#import "ThirdLevel.h"
#implementation ThirdLevel
#synthesize lista, categoria;
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"Categoria: %#", categoria);
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return NO;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//newtableView.separatorColor = [UIColor clearColor];
static NSString *CellIdentifier = "Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
}
- (void)buttonPressed:(id)sender {
NSLog(#"premuto");
}
- (void)dealloc {
[super dealloc];
}
#end
When i run it, the device crash and the debugger say that there is a EXC_BAD_ACCESS at this line:
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
i've the same code in the second level of the UINavigationController and it work fine, realy don't understand what's wrong.
Thanks for any help :)
static NSString *CellIdentifier =#"Cell";
not
static NSString *CellIdentifier = "Cell";
more over
return cell;//not found on ur code
May be you should return cell in this method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//newtableView.separatorColor = [UIColor clearColor];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
return cell;
}
Updated:
And as mentioned #AppleVijay add # when initializing CellIdentifier