Ios7 iOS 7内联日期选择器-不出现在单元格边界内

Ios7 iOS 7内联日期选择器-不出现在单元格边界内,ios7,uitableview,Ios7,Uitableview,我已经将用于内联显示PickerView的代码合并到以前的uitableview代码中。发生的情况是,pickerView的渲染超出了tableviewcell的边界 有人知道为什么我的单元格内容不显示在单元格边界中吗 我甚至删除了picker视图并使用标签进行测试,同样的事情也发生了。很明显,cell contentView出现了一些问题-我似乎无法锁定它 屏幕截图(单击以显示日期选择器之前): 问题屏幕截图(单击显示日期选择器后): 问题V2屏幕截图: (单元格剪辑边界为“是”) 情节

我已经将用于内联显示PickerView的代码合并到以前的uitableview代码中。发生的情况是,pickerView的渲染超出了tableviewcell的边界

有人知道为什么我的单元格内容不显示在单元格边界中吗

我甚至删除了picker视图并使用标签进行测试,同样的事情也发生了。很明显,cell contentView出现了一些问题-我似乎无法锁定它

屏幕截图(单击以显示日期选择器之前):

问题屏幕截图(单击显示日期选择器后):

问题V2屏幕截图: (单元格剪辑边界为“是”)

情节提要布局屏幕截图: (单元格具有绿色背景以显示可见性)

情节提要布局大纲屏幕截图:

代码:

ECNAddSessionViewController.h

@interface ECNAddSessionViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>

@end
通用设置方法

- (void)commonSetup {

    //initialize our Session
    self.session = [[Session alloc] init];

    self.dateFormatter = [[NSDateFormatter alloc] init];
    [self.dateFormatter setDateStyle:NSDateFormatterShortStyle]; // show short-style date format
    [self.dateFormatter setTimeStyle:NSDateFormatterNoStyle];

    // obtain the picker view cell's height, works because the cell was pre-defined in our storyboard
    UITableViewCell *pickerViewCellToCheck = [self.tableView dequeueReusableCellWithIdentifier:kECNAddSessionDatePickerCellIdentifier];
    self.pickerCellRowHeight = pickerViewCellToCheck.frame.size.height;
}
/*! Determines if the given indexPath has a cell below it with a UIDatePicker.

 @param indexPath The indexPath to check if its cell has a UIDatePicker below it.
 */
- (BOOL)hasPickerForIndexPath:(NSIndexPath *)indexPath {

    BOOL hasDatePicker = NO;

    NSInteger targetedRow = indexPath.row;
    targetedRow++;

    UITableViewCell *checkDatePickerCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:targetedRow inSection:0]];
    UIDatePicker *checkDatePicker = (UIDatePicker *)[checkDatePickerCell viewWithTag:kDatePickerTag];

    hasDatePicker = (checkDatePicker != nil);
    return hasDatePicker;
}

/*! Updates the UIDatePicker's value to match with the date of the cell above it.
 */
- (void)updateDatePicker {

    if (self.datePickerIndexPath != nil) {

        UITableViewCell *associatedDatePickerCell = [self.tableView cellForRowAtIndexPath:self.datePickerIndexPath];

        UIDatePicker *targetedDatePicker = (UIDatePicker *)[associatedDatePickerCell viewWithTag:kDatePickerTag];

        if (targetedDatePicker != nil) {

            // we found a UIDatePicker in this cell, so update it's date value
            if (self.session.date) {

                [targetedDatePicker setDate:self.session.date animated:NO];
            }
        }
    }
}

/*! Determines if the UITableViewController has a UIDatePicker in any of its cells.
 */
- (BOOL)hasInlineDatePicker {

    return (self.datePickerIndexPath != nil);
}

/*! Determines if the given indexPath points to a cell that contains the UIDatePicker.

 @param indexPath The indexPath to check if it represents a cell with the UIDatePicker.
 */
- (BOOL)indexPathHasPicker:(NSIndexPath *)indexPath {

    return ([self hasInlineDatePicker] && self.datePickerIndexPath.row == indexPath.row);
}

/*! Determines if the given indexPath points to a cell that contains the start/end dates.

 @param indexPath The indexPath to check if it represents start/end date cell.
 */
- (BOOL)indexPathHasDate:(NSIndexPath *)indexPath {

    BOOL hasDate = NO;

    if ((indexPath.row == kDateStartRow) || [self hasInlineDatePicker]) {

        hasDate = YES;
    }

    return hasDate;
}

/*! Adds or removes a UIDatePicker cell below the given indexPath.

 @param indexPath The indexPath to reveal the UIDatePicker.
 */
- (void)toggleDatePickerForSelectedIndexPath:(NSIndexPath *)indexPath {

    [self.tableView beginUpdates];

    NSArray *indexPaths = @[[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0]];

    // check if 'indexPath' has an attached date picker below it
    if ([self hasPickerForIndexPath:indexPath]) {

        // found a picker below it, so remove it
        [self.tableView deleteRowsAtIndexPaths:indexPaths
                              withRowAnimation:UITableViewRowAnimationFade];
    }else {

        // didn't find a picker below it, so we should insert it
        [self.tableView insertRowsAtIndexPaths:indexPaths
                              withRowAnimation:UITableViewRowAnimationFade];
    }

    [self.tableView endUpdates];
}
苹果提供的示例代码方法-略微调整

- (void)commonSetup {

    //initialize our Session
    self.session = [[Session alloc] init];

    self.dateFormatter = [[NSDateFormatter alloc] init];
    [self.dateFormatter setDateStyle:NSDateFormatterShortStyle]; // show short-style date format
    [self.dateFormatter setTimeStyle:NSDateFormatterNoStyle];

    // obtain the picker view cell's height, works because the cell was pre-defined in our storyboard
    UITableViewCell *pickerViewCellToCheck = [self.tableView dequeueReusableCellWithIdentifier:kECNAddSessionDatePickerCellIdentifier];
    self.pickerCellRowHeight = pickerViewCellToCheck.frame.size.height;
}
/*! Determines if the given indexPath has a cell below it with a UIDatePicker.

 @param indexPath The indexPath to check if its cell has a UIDatePicker below it.
 */
- (BOOL)hasPickerForIndexPath:(NSIndexPath *)indexPath {

    BOOL hasDatePicker = NO;

    NSInteger targetedRow = indexPath.row;
    targetedRow++;

    UITableViewCell *checkDatePickerCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:targetedRow inSection:0]];
    UIDatePicker *checkDatePicker = (UIDatePicker *)[checkDatePickerCell viewWithTag:kDatePickerTag];

    hasDatePicker = (checkDatePicker != nil);
    return hasDatePicker;
}

/*! Updates the UIDatePicker's value to match with the date of the cell above it.
 */
- (void)updateDatePicker {

    if (self.datePickerIndexPath != nil) {

        UITableViewCell *associatedDatePickerCell = [self.tableView cellForRowAtIndexPath:self.datePickerIndexPath];

        UIDatePicker *targetedDatePicker = (UIDatePicker *)[associatedDatePickerCell viewWithTag:kDatePickerTag];

        if (targetedDatePicker != nil) {

            // we found a UIDatePicker in this cell, so update it's date value
            if (self.session.date) {

                [targetedDatePicker setDate:self.session.date animated:NO];
            }
        }
    }
}

/*! Determines if the UITableViewController has a UIDatePicker in any of its cells.
 */
- (BOOL)hasInlineDatePicker {

    return (self.datePickerIndexPath != nil);
}

/*! Determines if the given indexPath points to a cell that contains the UIDatePicker.

 @param indexPath The indexPath to check if it represents a cell with the UIDatePicker.
 */
- (BOOL)indexPathHasPicker:(NSIndexPath *)indexPath {

    return ([self hasInlineDatePicker] && self.datePickerIndexPath.row == indexPath.row);
}

/*! Determines if the given indexPath points to a cell that contains the start/end dates.

 @param indexPath The indexPath to check if it represents start/end date cell.
 */
- (BOOL)indexPathHasDate:(NSIndexPath *)indexPath {

    BOOL hasDate = NO;

    if ((indexPath.row == kDateStartRow) || [self hasInlineDatePicker]) {

        hasDate = YES;
    }

    return hasDate;
}

/*! Adds or removes a UIDatePicker cell below the given indexPath.

 @param indexPath The indexPath to reveal the UIDatePicker.
 */
- (void)toggleDatePickerForSelectedIndexPath:(NSIndexPath *)indexPath {

    [self.tableView beginUpdates];

    NSArray *indexPaths = @[[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0]];

    // check if 'indexPath' has an attached date picker below it
    if ([self hasPickerForIndexPath:indexPath]) {

        // found a picker below it, so remove it
        [self.tableView deleteRowsAtIndexPaths:indexPaths
                              withRowAnimation:UITableViewRowAnimationFade];
    }else {

        // didn't find a picker below it, so we should insert it
        [self.tableView insertRowsAtIndexPaths:indexPaths
                              withRowAnimation:UITableViewRowAnimationFade];
    }

    [self.tableView endUpdates];
}
显示内联日期选择器方法

- (void)commonSetup {

    //initialize our Session
    self.session = [[Session alloc] init];

    self.dateFormatter = [[NSDateFormatter alloc] init];
    [self.dateFormatter setDateStyle:NSDateFormatterShortStyle]; // show short-style date format
    [self.dateFormatter setTimeStyle:NSDateFormatterNoStyle];

    // obtain the picker view cell's height, works because the cell was pre-defined in our storyboard
    UITableViewCell *pickerViewCellToCheck = [self.tableView dequeueReusableCellWithIdentifier:kECNAddSessionDatePickerCellIdentifier];
    self.pickerCellRowHeight = pickerViewCellToCheck.frame.size.height;
}
/*! Determines if the given indexPath has a cell below it with a UIDatePicker.

 @param indexPath The indexPath to check if its cell has a UIDatePicker below it.
 */
- (BOOL)hasPickerForIndexPath:(NSIndexPath *)indexPath {

    BOOL hasDatePicker = NO;

    NSInteger targetedRow = indexPath.row;
    targetedRow++;

    UITableViewCell *checkDatePickerCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:targetedRow inSection:0]];
    UIDatePicker *checkDatePicker = (UIDatePicker *)[checkDatePickerCell viewWithTag:kDatePickerTag];

    hasDatePicker = (checkDatePicker != nil);
    return hasDatePicker;
}

/*! Updates the UIDatePicker's value to match with the date of the cell above it.
 */
- (void)updateDatePicker {

    if (self.datePickerIndexPath != nil) {

        UITableViewCell *associatedDatePickerCell = [self.tableView cellForRowAtIndexPath:self.datePickerIndexPath];

        UIDatePicker *targetedDatePicker = (UIDatePicker *)[associatedDatePickerCell viewWithTag:kDatePickerTag];

        if (targetedDatePicker != nil) {

            // we found a UIDatePicker in this cell, so update it's date value
            if (self.session.date) {

                [targetedDatePicker setDate:self.session.date animated:NO];
            }
        }
    }
}

/*! Determines if the UITableViewController has a UIDatePicker in any of its cells.
 */
- (BOOL)hasInlineDatePicker {

    return (self.datePickerIndexPath != nil);
}

/*! Determines if the given indexPath points to a cell that contains the UIDatePicker.

 @param indexPath The indexPath to check if it represents a cell with the UIDatePicker.
 */
- (BOOL)indexPathHasPicker:(NSIndexPath *)indexPath {

    return ([self hasInlineDatePicker] && self.datePickerIndexPath.row == indexPath.row);
}

/*! Determines if the given indexPath points to a cell that contains the start/end dates.

 @param indexPath The indexPath to check if it represents start/end date cell.
 */
- (BOOL)indexPathHasDate:(NSIndexPath *)indexPath {

    BOOL hasDate = NO;

    if ((indexPath.row == kDateStartRow) || [self hasInlineDatePicker]) {

        hasDate = YES;
    }

    return hasDate;
}

/*! Adds or removes a UIDatePicker cell below the given indexPath.

 @param indexPath The indexPath to reveal the UIDatePicker.
 */
- (void)toggleDatePickerForSelectedIndexPath:(NSIndexPath *)indexPath {

    [self.tableView beginUpdates];

    NSArray *indexPaths = @[[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0]];

    // check if 'indexPath' has an attached date picker below it
    if ([self hasPickerForIndexPath:indexPath]) {

        // found a picker below it, so remove it
        [self.tableView deleteRowsAtIndexPaths:indexPaths
                              withRowAnimation:UITableViewRowAnimationFade];
    }else {

        // didn't find a picker below it, so we should insert it
        [self.tableView insertRowsAtIndexPaths:indexPaths
                              withRowAnimation:UITableViewRowAnimationFade];
    }

    [self.tableView endUpdates];
}
在多个部分中,我硬编码了1,使其只包含一个部分,就像苹果的示例代码一样,尽管最终tableview将包含三个部分

/*! Reveals the date picker inline for the given indexPath, called by "didSelectRowAtIndexPath".

 @param indexPath The indexPath to reveal the UIDatePicker.
 */
- (void)displayInlineDatePickerForRowAtIndexPath:(NSIndexPath *)indexPath {

    // display the date picker inline with the table content
    [self.tableView beginUpdates];

    BOOL before = NO;   // indicates if the date picker is below "indexPath", help us determine which row to reveal
    if ([self hasInlineDatePicker]) {

        before = self.datePickerIndexPath.row < indexPath.row;
    }

    BOOL sameCellClicked = (self.datePickerIndexPath.row - 1 == indexPath.row);

    // remove any date picker cell if it exists
    if ([self hasInlineDatePicker]) {

        [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:self.datePickerIndexPath.row inSection:0]]
                              withRowAnimation:UITableViewRowAnimationFade];
        self.datePickerIndexPath = nil;
    }

    if (!sameCellClicked) {

        // hide the old date picker and display the new one
        NSInteger rowToReveal = (before ? indexPath.row - 1 : indexPath.row);
        NSIndexPath *indexPathToReveal = [NSIndexPath indexPathForRow:rowToReveal inSection:0];

        [self toggleDatePickerForSelectedIndexPath:indexPathToReveal];
        self.datePickerIndexPath = [NSIndexPath indexPathForRow:indexPathToReveal.row + 1 inSection:0];
    }

    // always deselect the row containing the start or end date
    [self.tableView deselectRowAtIndexPath:indexPath animated:YES];

    [self.tableView endUpdates];

    // inform our date picker of the current date to match the current cell
    [self updateDatePicker];
}
单元配置

@interface ECNAddSessionViewController ()

@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) Session *session;

@property (nonatomic, strong) NSDateFormatter *dateFormatter;

// keep track which indexPath points to the cell with UIDatePicker
@property (nonatomic, strong) NSIndexPath *datePickerIndexPath;
@property (assign) NSInteger pickerCellRowHeight;
@property (nonatomic, strong) IBOutlet UIDatePicker *pickerView;

// this button appears only when the date picker is shown (iOS 6.1.x or earlier)
@property (nonatomic, strong) IBOutlet UIBarButtonItem *doneButton;

- (void)commonSetup;
- (void)registerForNotifications;
- (void)deregisterForNotifications;

- (IBAction)cancelAction:(UIButton *)sender;
- (IBAction)saveAction:(UIButton *)sender;

@end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = nil;

    switch (indexPath.section) {
        case AddSessionBasicInfoSection:

            switch (indexPath.row) {
                case 0: // session name cell
                {
                    cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionSessionNameCellIdentifier forIndexPath:indexPath];
                }
                    break;
                case 1: //company name cell
                {
                    cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionCompanyNameCellIdentifier forIndexPath:indexPath];

                }
                    break;
                case 2: // date cell
                {
                    cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionDateCellIdentifier forIndexPath:indexPath];

                    // we have either start or end date cells, populate their date field
                    cell.textLabel.text = [self.dateFormatter stringFromDate:self.session.date];
                }
                    break;
                case 3: // date picker cell
                {
                    cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionDatePickerCellIdentifier forIndexPath:indexPath];

                    NSLog(@"%@", indexPath);
                }
                    break;

            }
            break;
        case AddSessionTagsSection:

            cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionAddTagsCellIdentifier forIndexPath:indexPath];

            break;
        case AddSessionContentSection:

            cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionAddContentCellIdentifier forIndexPath:indexPath];

            break;
    }

    return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    if (cell.reuseIdentifier == kECNAddSessionDateCellIdentifier) {

        if (EMBEDDED_DATE_PICKER) {

            [self displayInlineDatePickerForRowAtIndexPath:indexPath];
        }else {

            [self displayExternalDatePickerForRowAtIndexPath:indexPath];
        }
    }else{

        [tableView deselectRowAtIndexPath:indexPath animated:YES];
    }
}
单元格选择

@interface ECNAddSessionViewController ()

@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) Session *session;

@property (nonatomic, strong) NSDateFormatter *dateFormatter;

// keep track which indexPath points to the cell with UIDatePicker
@property (nonatomic, strong) NSIndexPath *datePickerIndexPath;
@property (assign) NSInteger pickerCellRowHeight;
@property (nonatomic, strong) IBOutlet UIDatePicker *pickerView;

// this button appears only when the date picker is shown (iOS 6.1.x or earlier)
@property (nonatomic, strong) IBOutlet UIBarButtonItem *doneButton;

- (void)commonSetup;
- (void)registerForNotifications;
- (void)deregisterForNotifications;

- (IBAction)cancelAction:(UIButton *)sender;
- (IBAction)saveAction:(UIButton *)sender;

@end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = nil;

    switch (indexPath.section) {
        case AddSessionBasicInfoSection:

            switch (indexPath.row) {
                case 0: // session name cell
                {
                    cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionSessionNameCellIdentifier forIndexPath:indexPath];
                }
                    break;
                case 1: //company name cell
                {
                    cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionCompanyNameCellIdentifier forIndexPath:indexPath];

                }
                    break;
                case 2: // date cell
                {
                    cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionDateCellIdentifier forIndexPath:indexPath];

                    // we have either start or end date cells, populate their date field
                    cell.textLabel.text = [self.dateFormatter stringFromDate:self.session.date];
                }
                    break;
                case 3: // date picker cell
                {
                    cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionDatePickerCellIdentifier forIndexPath:indexPath];

                    NSLog(@"%@", indexPath);
                }
                    break;

            }
            break;
        case AddSessionTagsSection:

            cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionAddTagsCellIdentifier forIndexPath:indexPath];

            break;
        case AddSessionContentSection:

            cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionAddContentCellIdentifier forIndexPath:indexPath];

            break;
    }

    return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    if (cell.reuseIdentifier == kECNAddSessionDateCellIdentifier) {

        if (EMBEDDED_DATE_PICKER) {

            [self displayInlineDatePickerForRowAtIndexPath:indexPath];
        }else {

            [self displayExternalDatePickerForRowAtIndexPath:indexPath];
        }
    }else{

        [tableView deselectRowAtIndexPath:indexPath animated:YES];
    }
}

找到答案后,我觉得自己很愚蠢,因为它很简单,单元格没有得到任何高度值,应该早点找到这个值

在我的
-(void)commonSetup中,我从我的
datePickerCell
询问高度
方法,该方法将单元格出列并过早地获取其
frame.size.height

我不得不将下面的代码从
-(void)awakFromNib移动通过将代码移动到
-(void)viewDidLoad

// obtain the picker view cell's height, works because the cell was pre-defined in our storyboard
    UITableViewCell *pickerViewCellToCheck = [self.tableView dequeueReusableCellWithIdentifier:kECNAddSessionDatePickerCellIdentifier];
    self.pickerCellRowHeight = pickerViewCellToCheck.frame.size.height;
awakeFromNib
调用
commonSetup