我正在使用苹果提供的iOS7 Date Cell示例代码,其中tableViewController用于显示日期,并通过actionSheet以模态方式显示datePickers。我一直在尝试将单元格datePickerModes更改为datePickerModeDateAndTime,而datePickerModeTime仅用于学习目的但未成功。现在,他们都将成为datePickerModeDate。我不确定使用哪种方法来分配datePickerModes或如何单独挑出每个单元格来显示不同的选择器。我会使用if / else语句还是在viewWillAppear方法中分配它们?任何帮助是极大的赞赏。新手在这里。谢谢!
#define kTitleKey @"title" // key for obtaining the data source item's title
#define kDateKey @"date" // key for obtaining the data source item's date value
// keep track of which rows have date cells
#define kDateStartRow 1
#define kDateEndRow 2
#define kDateNewRow 3
static NSString *kDateCellID = @"dateCell"; // the cells with the start or end date
static NSString *kDatePickerID = @"datePicker"; // the cell containing the date picker
static NSString *kOtherCell = @"otherCell"; // the remaining cells at the end
#pragma mark -
@interface ActionSheetController ()
@property (nonatomic, strong) NSArray *dataArray;
@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;
@end
#pragma mark -
@implementation ActionSheetController
/*! Primary view has been loaded for this view controller
*/
- (void)viewDidLoad
{
[super viewDidLoad];
// setup our data source
NSMutableDictionary *itemOne = [@{ kTitleKey : @"Name it" } mutableCopy];
NSMutableDictionary *itemTwo = [@{ kTitleKey : @"Deadline",
kDateKey : [NSDate date] } mutableCopy];
NSMutableDictionary *itemThree = [@{ kTitleKey : @"Flashback day",
kDateKey : [NSDate date] } mutableCopy];
NSMutableDictionary *itemFour = [@{ kTitleKey : @"Flashback time",
kDateKey : [NSDate date] } mutableCopy];
NSMutableDictionary *itemFive = [@{ kTitleKey : @"" } mutableCopy];
self.dataArray = @[itemOne, itemTwo, itemThree, itemFour, itemFive];
self.dateFormatter = [[NSDateFormatter alloc] init];
[self.dateFormatter setDateStyle:NSDateFormatterMediumStyle]; // 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:kDatePickerID];
self.pickerCellRowHeight = pickerViewCellToCheck.frame.size.height;
}
#define EMBEDDED_DATE_PICKER (DeviceSystemMajorVersion() >= 7)
/*! 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
//
NSDictionary *itemData = self.dataArray[self.datePickerIndexPath.row - 1];
[targetedDatePicker setDate:[itemData valueForKey:kDateKey] 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) || (indexPath.row == kDateNewRow) ||
(indexPath.row == kDateEndRow || ([self hasInlineDatePicker] && (indexPath.row == kDateEndRow + 1))))
{
hasDate = YES;
}
return hasDate;
}
#pragma mark - UITableViewDataSource
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return ([self indexPathHasPicker:indexPath] ? self.pickerCellRowHeight : self.tableView.rowHeight);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self hasInlineDatePicker])
{
// we have a date picker, so allow for it in the number of rows in this section
NSInteger numRows = self.dataArray.count;
return ++numRows;
}
return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
NSString *cellID = kOtherCell;
if ([self indexPathHasPicker:indexPath])
{
// the indexPath is the one containing the inline date picker
cellID = kDatePickerID; // the current/opened date picker cell
}
else if ([self indexPathHasDate:indexPath])
{
// the indexPath is one that contains the date information
cellID = kDateCellID; // the start/end date cells
}
cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (indexPath.row == 0)
{
// we decide here that first cell in the table is not selectable (it's just an indicator)
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
// if we have a date picker open whose cell is above the cell we want to update,
// then we have one more cell than the model allows
//
NSInteger modelRow = indexPath.row;
if (self.datePickerIndexPath != nil && self.datePickerIndexPath.row < indexPath.row)
{
modelRow--;
}
NSDictionary *itemData = self.dataArray[modelRow];
// proceed to configure our cell
if ([cellID isEqualToString:kDateCellID])
{
// we have either start or end date cells, populate their date field
//
cell.textLabel.text = [itemData valueForKey:kTitleKey];
cell.detailTextLabel.text = [self.dateFormatter stringFromDate:[itemData valueForKey:kDateKey]];
}
else if ([cellID isEqualToString:kOtherCell])
{
// this cell is a non-date cell, just assign it's text label
//
cell.textLabel.text = [itemData valueForKey:kTitleKey];
}
return cell;
}
/*! 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];
}
/*! 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];
}
/*! Reveals the UIDatePicker as an external slide-in view, iOS 6.1.x and earlier, called by "didSelectRowAtIndexPath".
@param indexPath The indexPath used to display the UIDatePicker.
*/
- (void)displayExternalDatePickerForRowAtIndexPath:(NSIndexPath *)indexPath
{
// first update the date picker's date value according to our model
NSDictionary *itemData = self.dataArray[indexPath.row];
[self.pickerView setDate:[itemData valueForKey:kDateKey] animated:YES];
// the date picker might already be showing, so don't add it to our view
if (self.pickerView.superview == nil)
{
CGRect startFrame = self.pickerView.frame;
CGRect endFrame = self.pickerView.frame;
// the start position is below the bottom of the visible frame
startFrame.origin.y = self.view.frame.size.height;
// the end position is slid up by the height of the view
endFrame.origin.y = startFrame.origin.y - endFrame.size.height;
self.pickerView.frame = startFrame;
[self.view addSubview:self.pickerView];
// animate the date picker into view
[UIView animateWithDuration:kPickerAnimationDuration animations: ^{ self.pickerView.frame = endFrame; }
completion:^(BOOL finished) {
// add the "Done" button to the nav bar
self.navigationItem.rightBarButtonItem = self.doneButton;
}];
}
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.reuseIdentifier == kDateCellID)
{
if (EMBEDDED_DATE_PICKER)
[self displayInlineDatePickerForRowAtIndexPath:indexPath];
else
[self displayExternalDatePickerForRowAtIndexPath:indexPath];
}
else
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
答案 0 :(得分:2)
如果您查看故事板(MainStoryboard.storyboard),您可以看到他们已将日期选择器卡在其中一个表格视图单元格中(请参阅“表格视图单元格 - 日期选择器”)。请注意,日期选择器控件已被赋予标记99(在代码中,这是#define
'd为kDatePickerTag
)。
日期选择器是单元格的子视图,所以一旦你有一个指向包含选择器的单元格的指针,你就可以通过viewWithTag:
得到它,如:
UIDatePicker* picker = [cell viewWithTag:kDatePickerTag];
您可以在hasPickerForIndexPath:
和updateDatePicker:
中看到示例代码在多个位置执行此操作。后者是我在设置选择器模式的调用中堵塞的地方,如:
- (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
NSDictionary *itemData = self.dataArray[self.datePickerIndexPath.row - 1];
[targetedDatePicker setDate:[itemData valueForKey:kDateKey] animated:NO];
// Set the picker mode.
targetedDatePicker.datePickerMode = UIDatePickerModeDateAndTime;
}
}
}