我已将用于显示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];
}
}
答案 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}}