- (IBAction)readSlider:(id)sender {
CustomCell *cell; // <-- not set to the address of a cell
UISlider *theSlider=sender;
int progressAsInt=(int)(theSlider.value);
int tagValue=theSlider.tag; // <-- this is correct
NSLog(@"slider value is =%i",progressAsInt);
NSLog(@"slider tag is %i",tagValue); // <-- if this prints 0, the tag was never set
NSLog(@"celltag is", cell.tag); // <-- cell is a random address => crash
}
marklo wrote:
When the above code runs I get the slider value ok, but get a 0 for the slider tag and a BAD_EXEC for the cell tag.
The BAD_EXEC is easy to explain, since the cell variable was never set to the address of a cell. The above code to read and print the slider tag is correct, so it appears that tag wasn't set correctly.
Since your cells are made from a custom class, the reason the slider tags aren't being set could either be in your nib or in the cellForRowAtIndex (cell factory) data source method. For example, if an IBOutlet for the slider isn't connected in the nib, then cell.slider.tag=tag++ will fail in the cell factory because the 'slider' ivar will be nil.
Here's some sample code which tags the slider of each custom cell object and uses the tag to update an array of slider values:
// CustomCell.h
#import <UIKit/UIKit.h>
@interface CustomCell : UITableViewCell {
IBOutlet UILabel *nameLabel;
IBOutlet UISlider *slider;
}
@property (nonatomic, retain) UILabel *nameLabel;
@property (nonatomic, retain) UISlider *slider;
@end
// The nib for each cell consists of the custom cell, a label subview, and a slider subview, each of
// which is connected to the outlets defined above. In addition, the Value Changed event of the
// slider is connected to the myAction connector of File's Owner. Since File's Owner is set to 'self'
// in the CellsViewController implementation, the Value Changed event of each slider instance will
// fire the myAction method of the controller object
// CustomCell.m
#import "CustomCell.h"
@implementation CustomCell
@synthesize nameLabel;
@synthesize slider;
- (void)dealloc {
[nameLabel release];
[slider release];
[super dealloc];
}
@end
// CellsViewController.h
#import <UIKit/UIKit.h>
#define kTableViewRowCount 30
#define kTableViewRowHeight 66
@interface CellsViewController : UIViewController
<UITableViewDataSource, UITableViewDelegate> {
UITableView *theTableView;
NSMutableArray *sliderValues;
}
@property (nonatomic, retain)IBOutlet UITableView *theTableView;
@property (nonatomic, retain)NSMutableArray *sliderValues;
- (IBAction)myAction:(id)sender;
@end
// CellsViewController.m
#import "CellsViewController.h"
#import "CustomCell.h"
@implementation CellsViewController
@synthesize theTableView;
@synthesize sliderValues;
- (IBAction)myAction:(id)sender {
// NSLog(@"myAction: sender=%@", sender);
UISlider *theSlider = sender;
CustomCell *cell;
NSUInteger row = -1;
for (cell in [theTableView visibleCells]) {
// NSLog(@" cell=%@", cell);
if (cell.slider.tag == theSlider.tag) {
row = [[theTableView indexPathForCell:cell] row];
break;
}
}
if (row >=0 && row < kTableViewRowCount)
[self.sliderValues replaceObjectAtIndex:row
withObject:[NSNumber numberWithFloat:cell.slider.value]];
NSLog(@"myAction row=%d slider.tag=%d slider.value=%2.2f",
row, cell.slider.tag, cell.slider.value);
}
- (void)viewDidLoad {
[super viewDidLoad];
// initialize the slider data
self.sliderValues = [NSMutableArray arrayWithCapacity:kTableViewRowCount];
for (int iRow = 0; iRow < kTableViewRowCount; iRow++)
[self.sliderValues addObject:[NSNumber numberWithFloat:0.0]];
}
- (void)dealloc {
[theTableView release];
[sliderValues release];
[super dealloc];
}
#pragma mark -
#pragma mark Table Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView*)tableView
numberOfRowsInSection:(NSInteger)section {
return [sliderValues count];
}
- (UITableViewCell)tableView:(UITableView)tableView
cellForRowAtIndexPath:(NSIndexPath*)indexPath {
static NSString *CustomCellIdentifier = @"CustomCellIdentifier";
static NSUInteger nTag = 100;
CustomCell *cell = (CustomCell*)[tableView
dequeueReusableCellWithIdentifier:CustomCellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell"
owner:self options:nil];
cell = [nib objectAtIndex:0];
if (nTag <= 100)
NSLog(@"nib=%@", nib);
cell.slider.tag = nTag++;
NSLog(@"new cell: identifier=%@ slider.tag=%d",
[cell reuseIdentifier], cell.slider.tag);
}
int row = indexPath.row;
cell.nameLabel.text = [NSString stringWithFormat:@"Row %d", row];
cell.slider.value = [[self.sliderValues objectAtIndex:row] floatValue];
NSLog(@"cellForRowAtIndexPath: row=%d slider.tag=%d slider.value=%2.2f",
row, cell.slider.tag, cell.slider.value);
return cell;
}
#pragma mark -
#pragma mark Table Delegate Methods
- (CGFloat)tableView:(UITableView*)tableView
heightForRowAtIndexPath:(NSIndexPath*)indexPath {
return kTableViewRowHeight;
}
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
NSLog(@"didSelectRowAtIndexPath: row=%d", [indexPath row]);
CustomCell *cell = (CustomCell*)[tableView cellForRowAtIndexPath:indexPath];
UISlider *slider = cell.slider;
NSLog(@"Selected row=%d slider.tag=%d slider.value=%2.2f",
indexPath.row, slider.tag, slider.value);
}
@end
The example is based on the "Cells" project in Chapter 8 of +Beginning iPhone 3 Development: Exploring the iPhone SDK+ by Dave Mark and Jeff LaMarche. I can't recommend a better first book for iPhone developers. The projects in Chapter 8 will explain almost everything you need to successfully use table views in your apps.
Hope that helps!
- Ray