iOS 7内联DatePicker - 不出现在单元格边界内

时间:2014-04-16 21:50:57

标签: ios7 uitableview

我已将用于显示PickerView内联的Apple provided sample code (DateCell)合并到我以前的uitableview代码中。发生的事情是pickerView在tableviewcell的界限之外很好地呈现......

任何人都有任何想法,为什么我的单元格内容没有显示在单元格范围内?

我甚至删除了选择器视图并使用标签进行测试,同样的事情发生了。显然,单元格内容会发生变化 - 我似乎无法将其锁定......

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

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

问题V2截图: (单元格剪辑绑定为YES)

故事板布局截图: (单元格具有可见性的绿色背景)

故事板布局大纲屏幕截图:

代码:

ECNAddSessionViewController.h

@interface ECNAddSessionViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>

@end

ECNAddSessionViewController.m - 类别扩展

@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

CommonSetup方法

- (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;
}

Apple提供的示例代码方法 - 略有调整

/*! 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 - 只有一个像Apple的示例代码一样,尽管最终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];
}

UITableViewDataSource方法

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    return ([self indexPathHasPicker:indexPath] ? self.pickerCellRowHeight : self.tableView.rowHeight);
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1; //attempted to limit sections to just one (like Apple Sample Code)
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    NSInteger rows = 0;

    switch (section) {
        case AddSessionBasicInfoSection:

            //return three cells
            // name
            // company
            // date
            rows = 3;

            if ([self hasInlineDatePicker]) {

                // we have a date picker, so allow for it in the number of rows in this section
                return ++rows;
            }

            break;
        case AddSessionTagsSection:

            //return one cell
            rows = 1;
            break;
        case AddSessionContentSection:

            //return dynamic number of cells + the add content cell
            rows = 1;//TODO: Make Dynamic, Build Add Content feature
            break;
    }

    return rows;
}

单元格配置

- (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];
    }
}

1 个答案:

答案 0 :(得分:1)

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

我在我的datePickerCell方法中通过将- (void)commonSetup;排队并且过早地抓住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;

self.tableView

nil正在调用awakeFromNib时,commonSetup仍为{{1}}