2013-10-14 59 views
0

這是我從App最新截圖:從蘋果DateCell模板卸下電池

Screenshot

現在我想刪除單元格「標題」和兩個細胞「(等項目1)」和「 (其他項目2)'。我如何正確地做到這一點?我一直在收到錯誤。

這裏的MyTableViewController.m(由我編輯從here之前下載)

#import "MyTableViewController.h" 

#define kPickerAnimationDuration 0.40 // duration for the animation to slide the date picker into view 
#define kDatePickerTag    99  // view tag identifiying the date picker view 

#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 

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 MyTableViewController() 

@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 MyTableViewController 

/*! Primary view has been loaded for this view controller 
*/ 
- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // setup our data source 
    NSMutableDictionary *itemOne = [@{ kTitleKey : @"Title" } mutableCopy]; 
    NSMutableDictionary *itemTwo = [@{ kTitleKey : @"Startdatum", 
             kDateKey : [NSDate date] } mutableCopy]; 
    NSMutableDictionary *itemThree = [@{ kTitleKey : @"Enddatum", 
             kDateKey : [NSDate date] } mutableCopy]; 
    NSMutableDictionary *itemFour = [@{ kTitleKey : @"(other item1)" } mutableCopy]; 
    NSMutableDictionary *itemFive = [@{ kTitleKey : @"(other item2)" } mutableCopy]; 
    self.dataArray = @[itemOne, itemTwo, itemThree, itemFour, itemFive]; 

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

    // 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; 





    // if the local changes while in the background, we need to be notified so we can update the date 
    // format in the table view cells 
    // 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(localeChanged:) 
               name:NSCurrentLocaleDidChangeNotification 
               object:nil]; 
} 

- (void)dealloc 
{ 
    [[NSNotificationCenter defaultCenter] removeObserver:self 
                name:NSCurrentLocaleDidChangeNotification 
                object:nil]; 
} 


#pragma mark - Locale 

/*! Responds to region format or locale changes. 
*/ 
- (void)localeChanged:(NSNotification *)notif 
{ 
    // the user changed the locale (region format) in Settings, so we are notified here to 
    // update the date format in the table view cells 
    // 
    [self.tableView reloadData]; 
} 


#pragma mark - Utilities 

/*! Returns the major version of iOS, (i.e. for iOS 6.1.3 it returns 6) 
*/ 
NSUInteger DeviceSystemMajorVersion() 
{ 
    static NSUInteger _deviceSystemMajorVersion = -1; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 

     _deviceSystemMajorVersion = [[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."] objectAtIndex:0] intValue]; 
    }); 

    return _deviceSystemMajorVersion; 
} 

#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:2]]; 
    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 == kDateEndRow || ([self hasInlineDatePicker] && (indexPath.row == kDateEndRow + 1)))) 
    { 
     hasDate = YES; 
    } 

    return hasDate; 
} 


#pragma mark - UITableViewDataSource 


-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return 3; 
} 
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    return ([self indexPathHasPicker:indexPath] ? self.pickerCellRowHeight : self.tableView.rowHeight); 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    if (section == 2) { 
    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; 
    } else { 
     if (section == 0) { 
      return 2; 
     } else { 
      return 1; 
     } 


    } 
} 

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

    UITableViewCell *cell = nil; 
    if (indexPath.section <= 1) { 
     static NSString *CellIdentifier = @"Cell"; 


     // Configure the cell... 
     //UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
     cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
     if (!cell) { 
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
     } 

     if (indexPath.section == 0) { 
      switch (indexPath.row) { 
       case 0: 
        cell.textLabel.text = @"Hausaufgaben"; 
        cell.accessoryType = UITableViewCellAccessoryCheckmark; 
        break; 
       case 1: 
        cell.textLabel.text = @"Prüfung"; 
        break; 

       default: 
        break; 
      } 

     } else { 
      UITextField *lblMainLabel = [[UITextField alloc]initWithFrame:CGRectMake(50, 9, 150, 25)]; 
      lblMainLabel.tag = 42; 
      lblMainLabel.font = [UIFont fontWithName:@"Helvetica-Neue" size:15]; 
      lblMainLabel.textColor = [UIColor blackColor]; 
      lblMainLabel.placeholder = @"Beschreibung"; 
      [cell.contentView addSubview:lblMainLabel]; 
       cell.textLabel.text = @"Mat"; 
      cell.selectionStyle = UITableViewCellSelectionStyleNone; 

     } 
    } else { 
    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:2]]; 

    // 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:2]] 
           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:2]; 

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

    // 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 
{ 
    if (indexPath.section == 0) { 
     if (indexPath.row == 0) { 
      UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 
      cell.accessoryType = UITableViewCellAccessoryCheckmark; 
      UITableViewCell *cell2 = [[self tableView] cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; 
      cell2.accessoryType = UITableViewCellAccessoryNone; 
      [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; 


     }else { 
      UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 
      cell.accessoryType = UITableViewCellAccessoryCheckmark; 
      UITableViewCell *cell2 = [[self tableView] cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; 
      cell2.accessoryType = UITableViewCellAccessoryNone; 
      [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; 
     } 
      }else { 
    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]; 
    } 
    } 
} 


#pragma mark - Actions 

/*! User chose to change the date by changing the values inside the UIDatePicker. 

@param sender The sender for this action: UIDatePicker. 
*/ 
- (IBAction)dateAction:(id)sender 
{ 
    NSIndexPath *targetedCellIndexPath = nil; 

    if ([self hasInlineDatePicker]) 
    { 
     // inline date picker: update the cell's date "above" the date picker cell 
     // 
     targetedCellIndexPath = [NSIndexPath indexPathForRow:self.datePickerIndexPath.row - 1 inSection:2]; 
    } 
    else 
    { 
     // external date picker: update the current "selected" cell's date 
     targetedCellIndexPath = [self.tableView indexPathForSelectedRow]; 
    } 

    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:targetedCellIndexPath]; 
    UIDatePicker *targetedDatePicker = sender; 

    // update our data model 
    NSMutableDictionary *itemData = self.dataArray[targetedCellIndexPath.row]; 
    [itemData setValue:targetedDatePicker.date forKey:kDateKey]; 

    // update the cell's date string 
    cell.detailTextLabel.text = [self.dateFormatter stringFromDate:targetedDatePicker.date]; 
} 


/*! User chose to finish using the UIDatePicker by pressing the "Done" button, (used only for non-inline date picker), iOS 6.1.x or earlier 

@param sender The sender for this action: The "Done" UIBarButtonItem 
*/ 
- (IBAction)doneAction:(id)sender 
{ 
    CGRect pickerFrame = self.pickerView.frame; 
    pickerFrame.origin.y = self.view.frame.size.height; 

    // animate the date picker out of view 
    [UIView animateWithDuration:kPickerAnimationDuration animations: ^{ self.pickerView.frame = pickerFrame; } 
        completion:^(BOOL finished) { 
         [self.pickerView removeFromSuperview]; 
        }]; 

    // remove the "Done" button in the navigation bar 
    self.navigationItem.rightBarButtonItem = nil; 

    // deselect the current table cell 
    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 
    [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; 
} 

@end 

回答

1

我修改此示例代碼用於自己的應用程序。我做了一件事,我修改了ViewDidLoad中的MutableDictionary,將「其他單元格」文本更改爲@「」。這使得它基本上是空白的,然後我在故事板中清除了「其他單元格」背景。這可能會或可能不適合你。蘋果真的把這個代碼抽象出來了很多。您可以將字典中的日期信息移至位置0,將標題移至位置2.然後將最後3個鍵的值更改爲@「」。

這是我用來修改此示例代碼的方法。如果你像這樣開始,你可能會得到你想要去的地方。

這裏的是我的應用程序的截圖:

enter image description here

我不知道這是否會讓我張貼的圖片,我是新來這裏發帖。但下面是我最終使用的代碼,使用您使用的相同示例代碼進行tableview。我遺漏了一些導入,可能應該遺漏了更多不相關的代碼,但我只是發佈了整個tableViewController。我通過查看較舊版本的DateCell示例代碼來計算出了很多。它更簡單。但無論如何,希望這有助於。

#define kPickerAnimationDuration 0.40 // duration for the animation to slide the date picker into view 
#define kDatePickerTag    99  // view tag identifiying the date picker view 

#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 2 
#define kDateEndRow  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 EditShiftDetailViewController() 

@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 EditShiftDetailViewController 

/*! Primary view has been loaded for this view controller 
*/ 
- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)]; 
    gestureRecognizer.cancelsTouchesInView = NO; 
    [self.tableView addGestureRecognizer:gestureRecognizer]; 

    // setup our data source 
    NSMutableDictionary *itemOne = [@{ kTitleKey : @"Tap a cell to change its value:" } mutableCopy]; 
    NSMutableDictionary *itemTwo = [@{ kTitleKey : @"Shift Name:" } mutableCopy]; 
    NSMutableDictionary *itemThree = [@{ kTitleKey : @"Start Time", 
             kDateKey : self.currentShift.startTime } mutableCopy]; 
    NSMutableDictionary *itemFour = [@{ kTitleKey : @"End Time", 
             kDateKey : self.currentShift.endTime } mutableCopy]; 
    NSMutableDictionary *itemFive = [@{ kTitleKey : @"" } mutableCopy] ; 
    self.dataArray = @[itemOne, itemTwo, itemThree, itemFour, itemFive]; 


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

    // 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; 

    //self.shiftNameField.text = self.currentShift.shiftName; 

    self.title = [NSString stringWithFormat:@"%@, %@", self.currentDay.name, self.currentShift.shiftName]; 

    // if the local changes while in the background, we need to be notified so we can update the date 
    // format in the table view cells 
    // 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(localeChanged:) 
               name:NSCurrentLocaleDidChangeNotification 
               object:nil]; 
} 

- (void)viewWillDisappear:(BOOL)animated 
{ 
    [super viewWillDisappear:animated]; 
    self.currentShift.startTime = [self.dataArray[2] valueForKey:kDateKey]; 
    self.currentShift.endTime = [self.dataArray[3] valueForKey:kDateKey]; 
    [[MyManager sharedManager] saveChanges]; 
} 

- (void) hideKeyboard 
{ 
    [self.view endEditing:YES]; 
} 

- (void)dealloc 
{ 
    [[NSNotificationCenter defaultCenter] removeObserver:self 
                name:NSCurrentLocaleDidChangeNotification 
                object:nil]; 
} 


#pragma mark - Locale 

/*! Responds to region format or locale changes. 
*/ 
- (void)localeChanged:(NSNotification *)notif 
{ 
    // the user changed the locale (region format) in Settings, so we are notified here to 
    // update the date format in the table view cells 
    // 
    [self.tableView reloadData]; 
} 


#pragma mark - Utilities 

/*! Returns the major version of iOS, (i.e. for iOS 6.1.3 it returns 6) 
*/ 
NSUInteger DeviceSystemMajorVersion() 
{ 
    static NSUInteger _deviceSystemMajorVersion = -1; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 

     _deviceSystemMajorVersion = [[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."] objectAtIndex:0] intValue]; 
    }); 

    return _deviceSystemMajorVersion; 
} 

#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)indexPathHasShiftName:(NSIndexPath *)indexPath 
{ 
    return (indexPath.row == 1); 
} 

- (BOOL)indexPathHasDate:(NSIndexPath *)indexPath 
{ 
    BOOL hasDate = NO; 

    if ((indexPath.row == kDateStartRow) || 
     (indexPath.row == kDateEndRow || ([self hasInlineDatePicker] && (indexPath.row == kDateEndRow + 1)))) 
    { 
     hasDate = YES; 
    } 

    return hasDate; 
} 

- (BOOL)textFieldShouldReturn:(UITextField *)textField 
{ 
    [textField resignFirstResponder]; 
    self.currentShift.shiftName = textField.text; 
    self.title = [NSString stringWithFormat:@"%@, %@", self.currentDay.name, self.currentShift.shiftName]; 
    [self.tableView reloadData]; 

    return YES; 
} 

#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 
    } 
    else if ([self indexPathHasShiftName:indexPath]) 
    { 
     cellID = @"shiftNameCell"; 
    } 



    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:@"shiftNameCell"]) 
    { 
     UITextField *txtField = (UITextField *)[cell viewWithTag:8]; 
     txtField.delegate = self; 
     txtField.enablesReturnKeyAutomatically = YES; 
     txtField.returnKeyType = UIReturnKeyDone; 
     txtField.text = self.currentShift.shiftName; 
    } 
    else if ([cellID isEqualToString:kOtherCell]) 
    { 
     // this cell is a non-date cell, just assign it's text label 
     // 
     /*if (indexPath.row == 4) { 
      NSTimeInterval timeInterval = [self.currentShift.endTime timeIntervalSinceDate:self.currentShift.startTime]; 

      NSString *cellText = [self stringFromTimeInterval:timeInterval]; 

      cell.textLabel.text = [NSString stringWithFormat:@"Shift Length %@ hours", cellText]; 
     } else { */ 
     cell.textLabel.text = [itemData valueForKey:kTitleKey]; 
     // } 
    } 

    return cell; 
} 

- (NSString *)stringFromTimeInterval:(NSTimeInterval)interval { 
    NSInteger ti = (NSInteger)interval; 
    NSInteger minutes = (ti/60) % 60; 
    NSInteger hour = (ti/3600); 
    return [NSString stringWithFormat:@"%i:%02i", hour, minutes]; 
} 

/*! 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 setDatePickerMode:UIDatePickerModeTime]; 
    [self.pickerView setMinuteInterval:5]; 
    [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]; 

    } 
} 


#pragma mark - Actions 

/*! User chose to change the date by changing the values inside the UIDatePicker. 

@param sender The sender for this action: UIDatePicker. 
*/ 
- (IBAction)dateAction:(id)sender 
{ 
    NSIndexPath *targetedCellIndexPath = nil; 

    if ([self hasInlineDatePicker]) 
    { 
     // inline date picker: update the cell's date "above" the date picker cell 
     // 
     targetedCellIndexPath = [NSIndexPath indexPathForRow:self.datePickerIndexPath.row - 1 inSection:0]; 
    } 
    else 
    { 
     // external date picker: update the current "selected" cell's date 
     targetedCellIndexPath = [self.tableView indexPathForSelectedRow]; 
    } 

    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:targetedCellIndexPath]; 
    UIDatePicker *targetedDatePicker = sender; 

    // update our data model 
    NSMutableDictionary *itemData = self.dataArray[targetedCellIndexPath.row]; 
    [itemData setValue:targetedDatePicker.date forKey:kDateKey]; 

    // update the cell's date string 
    cell.detailTextLabel.text = [self.dateFormatter stringFromDate:targetedDatePicker.date]; 
    [[MyManager sharedManager] saveChanges]; 
    [self.tableView reloadData]; 
} 


/*! User chose to finish using the UIDatePicker by pressing the "Done" button, (used only for non-inline date picker), iOS 6.1.x or earlier 

@param sender The sender for this action: The "Done" UIBarButtonItem 
*/ 
- (IBAction)doneAction:(id)sender 
{ 
    CGRect pickerFrame = self.pickerView.frame; 
    pickerFrame.origin.y = self.view.frame.size.height; 

    // animate the date picker out of view 
    [UIView animateWithDuration:kPickerAnimationDuration animations: ^{ self.pickerView.frame = pickerFrame; } 
        completion:^(BOOL finished) { 
         [self.pickerView removeFromSuperview]; 
        }]; 

    // remove the "Done" button in the navigation bar 
    self.navigationItem.rightBarButtonItem = nil; 

    // deselect the current table cell 
    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 
    [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; 
} 

@end