简体   繁体   中英

Add xib as a view to cover a custom UITableViewCell in editing mode

I'm trying to to something like apple's alarm clock, when tap the edit button, a custom view cover the custom UITableViewCell .

The code above:

 // CGRect frame = [tableView rectForRowAtIndexPath:indexPath];
    // CGPoint yOffset = self.tableViewBlock.contentOffset;
    // CGRect newFrame = CGRectMake(frame.origin.x, (frame.origin.y - yOffset.y + 45), frame.size.width, frame.size.height);
    CallBlock_Date_EditMode *viewController = [[CallBlock_Date_EditMode alloc] initWithNibName:@"CallBlock_Date_EditMode" bundle:nil];

    // self.view.frame = newFrame;
    // [self.view addSubview:viewController.view];
    // [self addChildViewController:viewController];

    UITableViewCell *cell = (UITableViewCell*)[self.tableViewBlock cellForRowAtIndexPath:indexPath];
    [cell.contentView addSubview:viewController.view];

Cover the specific cell when I put in under:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  • Just to make sure the size is ok (although when I tap a button in that xib the app crash without even a single error).

But I want to do like apple's alarm clock (actually, mimic it), tap my edit button and my custom UITableViewCell will get cover with this xib as a view.

Maybe there is a better approach to do it?

EDIT:

My updated code is:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    CallBlock_TableCell *cell = (CallBlock_TableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    if (cell == nil)
    {
        cell = [[CallBlock_TableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    // Configure the cell...
    [self configureCell:cell atIndexPath:indexPath];

    return cell;
}

- (void)configureCell:(CallBlock_TableCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    cell.accessoryType = self.isEditing ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;

    CallBlock_ByDate *callBlock = (CallBlock_ByDate*)[fetchedObjects objectAtIndex:indexPath.row];
    cell.labelTime.text = callBlock.startDate;
    cell.labelRepeat.text = callBlock.repeat;
    cell.labelTextLabel.text = callBlock.label;
    cell.switchCallBlock.on = YES;
    cell.switchCallBlock.tag = (NSInteger)indexPath.row +1;
    [cell.switchCallBlock addTarget:self action:@selector(handleSwitch:) forControlEvents:UIControlEventValueChanged];
    cell.switchCallBlock.hidden = self.isEditing ? YES : NO;

    if (self.isEditing)
    {
        cell.switchCallBlock.hidden = YES;
        UIButton *btnArrow = [[UIButton alloc] init];
        btnArrow.frame = CGRectMake(282.0, 31.0, 18.0, 21.0);
        [btnArrow setBackgroundImage:[UIImage imageNamed:@"arrow_FWR_off"] forState:UIControlStateNormal];
        [btnArrow setBackgroundImage:[UIImage imageNamed:@"arrow_FWR_on"] forState:UIControlStateHighlighted];
        btnArrow = [UIButton buttonWithType:UIButtonTypeCustom];
        [btnArrow addTarget:self action:@selector(handleTapToEdit:) forControlEvents:UIControlEventTouchUpInside];
        btnArrow.tag = indexPath.row + 1;
        [cell.contentView addSubview:btnArrow];
        [cell.contentView bringSubviewToFront:btnArrow];
    }
}

But I cannot get the btnArrow appear on the UTableView .

The reason you are getting a crash is because nothing is retaining your CallBlock_Date_EditMode view controller. You add its view to your cell as a subview, but nothing maintains a reference to the view controller, so it is deallocated and then, when pressing a button that is supposed to pass a message to your view controller, it is sent to a deallocated object and you get a crash.

There are two possible solutions to this. First, you could store that view controller in one of your properties to maintain a reference to it so that it does not deallocated. This is, for the most part, probably not what you want.

Instead, what I would suggest doing is do not make your CallBlock_Date_EditMode a UIViewController, but instead make it a UIView. You may be wondering "But how can I use a xib without a UIViewController?". I would do something like the following:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        UIView *view = [[[NSBundle mainBundle] loadNibNamed:@"CallBlock_Date_EditMode" owner:self options:nil] objectAtIndex:0];
        self.myEditButton = (UIButton *)[view viewWithTag:2];

        [self addSubview:view];
    }
    return self;
}

This would be code inside your custom UIView that would load in a xib file and add it as a subview. In order to get access to your subviews, you have to use tags inside interface builder, so you do lose the convenience of drawing/connecting IBOutlets... But in the end, it is much better than allocating/storing a bunch of unnecessary UIViewControllers.

If I understand you right and you want to mimic the functionality of the alarm clock that comes pre-installed from Apple, your solution is much simpler than creating a custom view. It looks like all they do is set the On-Off switches to hidden and add a disclosure indicator to the cell. This is what I would do...

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
      static NSString *CellIdentifier = @"Cell";
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

      bool hide = (tableView.editingStyle == UITableViewCellEditingStyleDelete); // set to true or false depending on if the table is in editing mode

      for (UIView *sv in [cell subviews] ) { 
           if([sv isKindOfClass:[UISwitch class]]) { // find the on-off switch
                [sv setHidden:hide]; // hide the switch depending on the t/f value of hide
                break;
           }
      }
      if(hide) { // adds the arrow like in apple's alarm clock table if the cell is in edit mode
           [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
      }
      else {
           [cell setAccessoryType:UITableViewCellAccessoryNone];
      }

 return cell;
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM