Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID
Please do not post the same thing multiple times. The board software automatically flags certain posts as needing moderator attention. This happens the most often for new users. I'm pretty sure this is made clear at the time you attempt to post. Posting the same thing over and over again just makes that many more posts the moderators have to weed through later. This makes us sad. Don't make us sad. If your post/thread doesn't appear, just wait a while. Don't post it again. If it hasn't shown up by the next day, then you can try again. I normally go through posts in the mornings, and try to check a few times throughout the day, but I'm not here 24/7. There will typically be a significant delay before posts are approved. Just be patient.

Multiplying Switch in Tableview Cell

Please help me learn what is happening and wrong.

The situation: Building a 4 section, varying rows tableview, using a subclass of Tableview Cell in storyboard with dynamic prototypes. Everything is running fine until I added a UISwitch (just in 2 rows). They appear 'initially' at the correct indexPath, but after scrolling, they begin appearing where they aren't supposed to be.

I've tried many different ideas, all of which change nothing... reuse identifiers & [cell.comboLabel addSubview:nil] in the 'non switch' rows.

Here's where I am.
(The 2 connected cell textFields are: nameLabel & comboLabel)


NSArray *a = [[userDetailData objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];

NSString *key = [[[a objectAtIndex:0] allKeys] objectAtIndex:0];
NSString *value = [[a objectAtIndex:0] valueForKey:key];

static NSString *CellIdentifier = @\"MasterCell\";

UsersTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

// Configure the cell...
if (cell == nil)
{
// Do anything that should be the same on EACH cell here. Fonts, colors, etc.
// ** This is not being logged, ever **
NSLog(@\" (%@,%@) Cell = nil\", [indexPath section], [indexPath row] );
}

// Do anything that COULD be different on each cell here. Text, images, etc.
// Set the Item
cell.nameLabel.text = [NSString stringWithFormat:@\"%@\", key];

... other cell configuration

// Put On/Off switch in Password 'On' fields
if ([key isEqualToString:@\"On\"])
{
UISwitch *aSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(152, 4, 0, 0)];
if (!value)
[aSwitch setOn:YES animated:NO];
else
[aSwitch setOn:NO animated:NO];

[aSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
cell.comboLabel.text = nil;
cell.comboLabel.clipsToBounds = NO;
[cell.comboLabel addSubview:aSwitch];
}
else
{
cell.comboLabel.text = [NSString stringWithFormat: @\"%@\",value];
}

Any suggestions?
Post edited by dolan on

Replies

  • Duncan CDuncan C Posts: 8,021Tutorial Authors, Registered Users
    dolan;406402 said:
    Please help me learn what is happening and wrong.

    The situation: Building a 4 section, varying rows tableview, using a subclass of Tableview Cell in storyboard with dynamic prototypes. Everything is running fine until I added a UISwitch (just in 2 rows). They appear 'initially' at the correct indexPath, but after scrolling, they begin appearing where they aren't supposed to be.

    I've tried many different ideas, all of which change nothing... reuse identifiers & [cell.comboLabel addSubview:nil] in the 'non switch' rows.

    Here's where I am.
    (The 2 connected cell textFields are: nameLabel & comboLabel)


    NSArray *a = [[userDetailData objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];

    NSString *key = [[[a objectAtIndex:0] allKeys] objectAtIndex:0];
    NSString *value = [[a objectAtIndex:0] valueForKey:key];

    static NSString *CellIdentifier = @\"MasterCell\";

    UsersTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Configure the cell...
    if (cell == nil)
    {
    // Do anything that should be the same on EACH cell here. Fonts, colors, etc.
    // ** This is not being logged, ever **
    NSLog(@\" (%@,%@) Cell = nil\", [indexPath section], [indexPath row] );
    }

    // Do anything that COULD be different on each cell here. Text, images, etc.
    // Set the Item
    cell.nameLabel.text = [NSString stringWithFormat:@\"%@\", key];

    ... other cell configuration

    // Put On/Off switch in Password 'On' fields
    if ([key isEqualToString:@\"On\"])
    {
    UISwitch *aSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(152, 4, 0, 0)];
    if (!value)
    [aSwitch setOn:YES animated:NO];
    else
    [aSwitch setOn:NO animated:NO];

    [aSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
    cell.comboLabel.text = nil;
    cell.comboLabel.clipsToBounds = NO;
    [cell.comboLabel addSubview:aSwitch];
    }
    else
    {
    cell.comboLabel.text = [NSString stringWithFormat: @\"%@\",value];
    }

    Any suggestions?
    You should use a unique cell reuse identifier for cells that have a different structure. If you have a subset of your cells that have a segmented control in them, let's call those cells "segmentedCell". Ask for a "segmentedCell" when you try to dequeue a reused cell. Then, if no "segmentedCell" is available, create a cell using that identifier.

    The idea is that you create cells of different types, and recycle them in that type. (You sort bottles, cans, and newspapers separately. If you need some newspaper to wrap fish, you ask for recycled newspaper. If you just ask for some recycled stuff, you might get a bottle instead, and you can't wrap up fish with a bottle.)

    Once you have each type of cell being created and recycled in separate "recycling bins", you always get the correct type of cell, or are told there aren't any of that type.

    Once you have a cell with the correct structure (layout of fields) you need to completely configure it, setting all values, including forcing fields to an empty/starting state if you don't use them.
    Regards,

    Duncan C
    WareTo

    mug

    Animated GIF created with Face Dancer, available for free in the app store.
  • dolandolan Posts: 3New Users
    Thanks for replying Duncan.
    Duncan C;406409 said:

    The idea is that you create cells of different types, and recycle them in that type. (You sort bottles, cans, and newspapers separately. If you need some newspaper to wrap fish, you ask for recycled newspaper. If you just ask for some recycled stuff, you might get a bottle instead, and you can't wrap up fish with a bottle.)
    Are you suggesting that my code for the cell needs to be (almost) duplicated?

    In form:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    NSArray *a = [[userDetailData objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];

    NSString *key = [[[a objectAtIndex:0] allKeys] objectAtIndex:0];
    NSString *value = [[a objectAtIndex:0] valueForKey:key];

    static NSString *CellIdentifier;
    UsersTableViewCell *cell;
    // Put On/Off switch in Password 'On' fields
    if ([key isEqualToString:@\"On\"]) {
    CellIdentifier = @\"SwitchCell\";
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Build the rest of the 'UISwitch' cell
    .... cell. {property} = ...
    }
    else {
    CellIdentifier = @\"MasterCell\";
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Build the rest of the 'Usual' cell
    .... cell. {property} = ...
    }
    return cell;
    }
  • Duncan CDuncan C Posts: 8,021Tutorial Authors, Registered Users
    dolan;406410 said:
    Thanks for replying Duncan.


    Are you suggesting that my code for the cell needs to be (almost) duplicated?

    In form:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    NSArray *a = [[userDetailData objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];

    NSString *key = [[[a objectAtIndex:0] allKeys] objectAtIndex:0];
    NSString *value = [[a objectAtIndex:0] valueForKey:key];

    static NSString *CellIdentifier;
    UsersTableViewCell *cell;
    // Put On/Off switch in Password 'On' fields
    if ([key isEqualToString:@\"On\"]) {
    CellIdentifier = @\"SwitchCell\";
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Build the rest of the 'UISwitch' cell
    .... cell. {property} = ...
    }
    else {
    CellIdentifier = @\"MasterCell\";
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Build the rest of the 'Usual' cell
    .... cell. {property} = ...
    }
    return cell;
    }

    Sort of, yes.

    You are writing a factory that creates table view cells cells. It first looks for a recycled cell of the correct type. If it finds one, it sets all it's values and returns it. If it doesn't find it, it needs to build it.

    It may be that you can make your code modular. IF all your cells have common elements, and the only difference for your cells that have a segmented control is the segmented control, then you could structure your code so the shared setup is only done once (in a separate method, maybe?)
    Regards,

    Duncan C
    WareTo

    mug

    Animated GIF created with Face Dancer, available for free in the app store.
Sign In or Register to comment.