Reputation: 8309
I have 3 segmented controls in each cell of a tableview on an iPad. The orientation is always landscape for the app and the number of cells vary for each run on the app. The app performs fine if the number of rows are around less than 10, but anywhere above that, the glitches start to appear.
For the kind of application I'm building, I could have as many as 70 rows ==> meaning, 210 UISegmentedControls, all alloced in the memory at once.
Is there a work around? Is there a way I can reuse these UISegmentedControls? If yes, how can I preserve the state of the segmented control?
Otherwise, can anybody propose a new solution? (Each segmented control has items 'A' and 'B' and there are three segmented controls representing three different parameters for each object corresponding to each row of the table).
Here's the 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];
}
// Configure the cell...
segmentedControl1 = (UISegmentedControl*)[array1 objectAtIndex:[indexPath row]];
segmentedControl1.frame = CGRectMake(180, 15, 100, 30);
[cell.contentView addSubview:segmentedControl1];
segmentedControl2 = (UISegmentedControl*)[array2 objectAtIndex:[indexPath row]];
segmentedControl2.frame = CGRectMake(450, 15, 100, 30);
[cell.contentView addSubview:segmentedControl2];
segmentedControl3 = (UISegmentedControl*)[array3 objectAtIndex:[indexPath row]];
segmentedControl3.frame = CGRectMake(725, 15, 100, 30);
[cell.contentView addSubview:segmentedControl3];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Upvotes: 1
Views: 590
Reputation: 8207
You should be re-using UITableViewCells, which contain three generic UISegmentedControls. When tableView:cellForRowAtIndexPath: is called, you should set the correct values for each segmented control - always.
Those values have to be stored "somewhere else", outside cells, most likely in same place as where you get the other data for cells.
Update with draft code, should not compile as-is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = @"CellId";
static NSString *cellNib = @"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:cellNib owner:self options:nil];
for (id nibItem in nib)
{
if ([nibItem isKindOfClass:[UITableViewCell class]])
{
cell = (UITableViewCell *)nibItem;
break;
}
}
}
// Configure the cell, all values!
UISegmentedControl *seg = nil;
seg = (UISegmentedControl *)[cell viewWithTag:1];
seg.selectedSegmentIndex = 0
UISegmentedControl *seg = nil;
seg = (UISegmentedControl *)[cell viewWithTag:2];
seg.selectedSegmentIndex = 0
return cell;
}
The idea is that you create a custom UITableViewCell template in Interface Builder with 3 segmented Controls. Give each control a UNIQUE tag id number. Use the tag id to get access to each specific control and setup ALL VALUES - because you are reusing the same cells and by default they will contain old values.
Btw about cell non-selection... Well, there are many ways to do that, wrote even a blog about it "How to Disable UITableCell Selection". Yep, it's old and got title wrong, but should work.
Hope this helps :)
Upvotes: 1
Reputation: 15376
Create a custom UITableViewCell
subclass. Have three properties in it for your three UISegmentedControl
s and add them in the init
method:
@interfate MyCell : UITableViewCell
@property (nonatomic, retain, readonly) UISegmentedControl *control1;
@property (nonatomic, retain, readonly) UISegmentedControl *control2;
@property (nonatomic, retain, readonly) UISegmentedControl *control3;
@end
@implementation
@synthesize control1 = _control1;
@synthesize control2 = _control2;
@synthesize control3 = _control2;
- (id)init
{
if ((self = [super init]))
{
_control1 = [[UISegmentedControl alloc] init...];
_control1.frame = CGRectMake(...);
[self addSubView:_control1];
// repeat with control2 & control3
}
//...
@end
Then, rather than storing arrays of UISegmentedControl
s you can then have arrays of NSNumber
holding the selected index.
You'd then do something like:
cell.control1.selectedIndex = [[array1 objectAtIndex:indexPath.row] integerValue];
You could also create custom objects to hold this data and store them in one array.
Upvotes: 1
Reputation:
You can allocate the segmented controls in your cell for row at index path when the cells are being created. Allocate them in cell for row at index path. Allocate and add the segmented controls under the (cell == nil) condition.
Or
You can reuse 3 segmented controls for all the cells. And hold an array for keeping the changed values.
Upvotes: 0
Reputation: 3429
I suspect that your problem is something other than segmented controls. A UITableView has built-in methods to take care of loading and reloading classes as they go off-screen, so all 210 controls should not be in memory at once.
I would start by checking to make sure that you are using dequeueReusableCellWithIdentifier:
correctly (especially if each UITableViewCell is the same class). Maybe also check for memory leaks.
Upvotes: 0
Reputation: 47729
I've never seen a UITableView keep "live" more than one or two cells beyond those visible on the screen. Are you using dequeueReusableCellWithIdentifier to recycle your cells?
Upvotes: 0