Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
($1.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 09-07-2011, 01:42 PM   #1 (permalink)
Registered Member
 
Join Date: Feb 2009
Posts: 218
malaki1974 is on a distinguished road
Default uisegmentcontrol selected in a uitableview

Hello,

I have a custom tablecell with some labels and images and a uisegmented control. When I load the cell into the table everything is wired properly in that the right images show up, the labels are loaded properly with correct text and the uisegment control titles are set. However when I make a selection on the uisegment control and then scroll it does not work properly. Random uisegment controls further down when you scroll show up as selected and when you scroll back the previously selected uisegs are deselected (the default).

I know it has to do with dequeing but am unsure how to fix. I think I need to save the state of the uiseg in an array and then reset when it scrolls onscreen but I am not sure how to do that.

Code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
	
	User *user = nil;
	NSInteger row = [indexPath row];
	
	static NSString *CellIdentifier = @"tableCell";
    static NSString *CellNib = @"tableCell";
	
    tableCell *cell = (tableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
        cell = (tableCell *)[nib objectAtIndex:0];
    }
		
	if (tableView == [[self searchDisplayController] searchResultsTableView]) {
		user = [[self filteredListItems] objectAtIndex:row];
	} else {
		user = [[self userArrayData] objectAtIndex:row];
	}

	NSString *urlString = [NSString stringWithFormat: @"%@", user.icon];
	NSString *urllString = [NSString stringWithFormat: @"%@", user.screen];
	// Here we use the new provided setImageWithURL: method to load the web image
    [cell.imageView setImageWithURL:[NSURL URLWithString:urlString]
                   placeholderImage:[UIImage imageNamed:@"placeholderIcon@2x.png"]];
	[cell.imagedView setImageWithURL:[NSURL URLWithString:urllString]
                   placeholderImage:[UIImage imageNamed:@"placeholderIcon@2x.png"]];
	
	[cell.segControl setTitle:user.name forSegmentAtIndex:0];
	[cell.segControl setTitle:user.client forSegmentAtIndex:1];
	//cell.segControl.selectedSegmentIndex = UISegmentedControlNoSegment;
	[cell.segControl addTarget:self action:@selector(makePick:) forControlEvents:UIControlEventValueChanged];	

    return cell;
}
malaki1974 is offline   Reply With Quote
Old 09-07-2011, 02:44 PM   #2 (permalink)
Senior Member
iPhone Dev SDK Supporter
 
Join Date: Aug 2008
Location: Memphis, TN, USA
Age: 24
Posts: 3,983
smithdale87 is on a distinguished road
Send a message via AIM to smithdale87
Default

Right, it definitely has to do with the de-queuing and cells being reused. In your cellForRowAtIndexPath, you always need to reset the segmented control selected index to the last known state, which means you need a way to save the state. You could set this up in your makePick: method since you alreadh have that as a target for when the value changes.

All you would need to do is get the indexpath of the cell, and store the value of the segmented control in an NSMutableDictionary, letting the indexpath of the row be the key in the dictionary. You could read the contents from teh dictionary in the same way so that you can set the selected index of the segmented control in your cellForRowAtIndexPath.
smithdale87 is offline   Reply With Quote
Old 09-07-2011, 03:11 PM   #3 (permalink)
Registered Member
 
Join Date: Feb 2009
Posts: 218
malaki1974 is on a distinguished road
Default

Here is my new code but the tag is not coming across:
Code:
-

(IBAction)makePick:(id)sender {
	
	int btn = ((UISegmentedControl *)sender).tag;
	int myPick = ((UISegmentedControl *)sender).selectedSegmentIndex;
	
	NSLog(@"My tag = %i myPick = %i",btn, myPick);
	
	[tempArray addObject:[NSNumber numberWithInt:btn]];
	NSLog(@"%@",tempArray);
	
	myPick = [(UISegmentedControl *)sender titleForSegmentAtIndex:[(UISegmentedControl *)sender selectedSegmentIndex]];
	NSLog(@"My pick = %@",myPick);
}
I am maybe closer however...
malaki1974 is offline   Reply With Quote
Old 09-08-2011, 11:23 AM   #4 (permalink)
Registered Member
 
Join Date: Feb 2009
Posts: 218
malaki1974 is on a distinguished road
Default

Riddle me this, Batman. Closer still. This will not update the values and in fact crashes when I scroll back up from the bottom with the following error in the console:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSMutableArray objectAtIndex:]: index 1 beyond bounds [0 .. 0]'

I think this is really close to updating the uisegcontrol when you scroll. Can anyone take a look? As a quick note I set up my nsmarray with 16 nsmarrays of 2 nsnumbers - one of the row and one of the segment selected like so:
Code:
[[[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:row], [NSNumber numberWithInt:myyPick],nil] autorelease],nil];
Code:
-(IBAction)makePick:(id)sender {
	
	UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
	NSIndexPath *clickedButtonPath = [self.listTableView indexPathForCell:clickedCell];
	
	int row = [clickedButtonPath row];
	NSLog(@"my row %i", row);
	int myyPick = ((UISegmentedControl *)sender).selectedSegmentIndex;
	NSLog(@"my selected %i", myyPick);
	
	NSArray *newArray =  [[NSMutableArray alloc] initWithObjects:
				  [[[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:row], [NSNumber numberWithInt:myyPick],nil] autorelease],nil];

    [tempArray replaceObjectAtIndex:row withObject:newArray];
	NSLog(@"Away array is %@",tempArray);

	myPick = [(UISegmentedControl *)sender titleForSegmentAtIndex:[(UISegmentedControl *)sender selectedSegmentIndex]];
	NSLog(@"My pick = %@",myPick);
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
	User *user = nil;
	NSInteger row = indexPath.row;
	
	if (tableView == [[self searchDisplayController] searchResultsTableView]) {
		user = [[self filteredListItems] objectAtIndex:row];
	} else {
		user = [[self userArrayData] objectAtIndex:row];
	}
	
	static NSString *CellIdentifier = @"tableCell";
    static NSString *CellNib = @"tableCell";

    tableCell *cell = (tableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
        cell = (tableCell *)[nib objectAtIndex:0];
		[cell.segControl addTarget:self action:@selector(makePick:) forControlEvents:UIControlEventValueChanged];
		cell.segControl.selectedSegmentIndex = UISegmentedControlNoSegment;
	}

	NSString *urlString = [NSString stringWithFormat: @"%@", user.icon];
	NSString *urllString = [NSString stringWithFormat: @"%@", user.screen];
	// Here we use the new provided setImageWithURL: method to load the web image
    [cell.imageView setImageWithURL:[NSURL URLWithString:urlString]
                   placeholderImage:[UIImage imageNamed:@"placeholderIcon@2x.png"]];
	[cell.imagedView setImageWithURL:[NSURL URLWithString:urllString]
                   placeholderImage:[UIImage imageNamed:@"placeholderIcon@2x.png"]];
	
	[cell.segControl setTitle:user.name forSegmentAtIndex:0];
	[cell.segControl setTitle:user.client forSegmentAtIndex:1];
	
	NSNumber *checkValue = [[tempArray objectAtIndex:row] objectAtIndex:1]; -- where the error above comes in
	NSLog(@"checkValue is %d", [checkValue intValue]);
	// Reusing cell; make sure it has correct image based on checkRepeatState value
	cell.segControl = (UISegmentedControl*)[cell viewWithTag:1];
	
	if ([checkValue intValue] == 1) {
		NSLog(@"right is selected");
		segControl.selectedSegmentIndex = 1;
	} else {
		NSLog(@"right is NOT selected");
		segControl.selectedSegmentIndex = 0;
	}

   return cell;
}
malaki1974 is offline   Reply With Quote
Old 09-08-2011, 11:33 AM   #5 (permalink)
Registered Member
 
Join Date: Feb 2009
Posts: 218
malaki1974 is on a distinguished road
Default

This might be something. I can see in the console the array is updating but it has a different format than the original. It has an extra set of parentheses around each.
Code:
Home array is (
        (
        0,
        0
    ),
now looks like
Code:
Away array is (
        (
                (
            0,
            1
        )
    ),
malaki1974 is offline   Reply With Quote
Old 09-08-2011, 11:36 AM   #6 (permalink)
Senior Member
iPhone Dev SDK Supporter
 
Join Date: Aug 2008
Location: Memphis, TN, USA
Age: 24
Posts: 3,983
smithdale87 is on a distinguished road
Send a message via AIM to smithdale87
Default

Right, the first one is just an array of 0's. The second one is an array of arrays. It sounds like you just need to initailize your home array to contain arrays of 2 integers each, rather than just a single array.
smithdale87 is offline   Reply With Quote
Old 09-08-2011, 12:22 PM   #7 (permalink)
Registered Member
 
Join Date: Oct 2010
Location: Atlanta, GA
Posts: 148
tripp13 is on a distinguished road
Default

Are you going to be adding anymore cells to the tableView, i.e. are cells added dynamically by the user, or are the total number of rows set with no new rows being added? How many total rows do you have?

If you're not adding anymore rows to the tableView, or the total number of shares you anticipate the user to add will not be a large number, don't make the cells reusable. Change:

Code:
tableCell *cell = (tableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
to this:

Code:
UITableViewCell *cell = nil;
// OR
UITableViewCell *cell;
Now, your cells are not reused and they are not reset (I think that's how I solved my problem, but I will have to double check).

Try it out and see if that solves the problem for you.
tripp13 is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 372
8 members and 364 guests
apatsufas, JackReidy, jeroenkeij, Sami Gh, tim0504, UMAD, yomo710
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,671
Threads: 94,121
Posts: 402,904
Top Poster: BrianSlick (7,990)
Welcome to our newest member, JackReidy
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 04:54 AM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0