2013-09-16 3 views
0

Я использую образец кода, представленный яблоки для iOS7 Date Cell, где tableViewController используется для отображения дат и даты представления datePickers с помощью ActionSheet. Я пытаюсь изменить ячейки datePickerModes на datePickerModeDateAndTime и datePickerModeTime только для учебных целей, но они не увенчались успехом. Прямо сейчас все они появляются как datePickerModeDate. Я не уверен, какой метод использовать для назначения datePickerModes или как индивидуально выделить каждую ячейку для отображения другого выбора. Я бы использовал оператор if/else или назначил бы их в методе viewWillAppear? любая помощь очень ценится. новичок здесь. благодаря!Как изменить datePickerMode для отдельных ячеек в UITableViewController?

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

ответ

2

Если посмотреть на раскадровке (MainStoryboard.storyboard) вы можете увидеть, что они заклинили выбор даты прямо в одном из видовых таблиц ячеек (см «Table View Cell - Datepicker»). Обратите внимание, что для элемента управления выбора даты был присвоен тег 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; 
     } 
    } 
} 
+0

Отлично! Теперь, если бы я хотел установить один сборщик в UIDatePickerModeDateAndTime, другой - в UIDatePickerModeDate, а последний - в UIDatePickerModeTime, это то, что строка/метод, который я бы назначил каждой ячейке, это собственный pickerMode? и было бы, если бы/было бы лучшим способом добиться этого? –

+0

Да, это то место, где я бы это сделал, и просто если/else все будет в порядке. Вы можете проверить self.datePickerIndexPath.row и установить режим на основе этого. – zpasternack

Смежные вопросы