iOS 7 - 如何在表格视图中显示日期选择器?

Posted

技术标签:

【中文标题】iOS 7 - 如何在表格视图中显示日期选择器?【英文标题】:iOS 7 - How to display a date picker in place in a table view? 【发布时间】:2013-09-29 04:40:30 【问题描述】:

在 WWDC 2013 视频中,Apple 建议在 ios 7 的表格视图中显示选取器。如何在表格视图单元格之间插入视图并为其设置动画?

像这样,来自 Apple 日历应用程序:

【问题讨论】:

这是哪个 WWDC 视频?我试图了解为什么这是特定于 iOS7 的,以及是否有原因在早期版本上无法做到这一点。 找到了,它是“iOS 用户界面设计中的新功能”(感谢 ASCIIwwdc)。基本原理是旧样式看起来不正确,但新的扁平外观确实如此。 请查看:The easiest way to use DateCell in Swift 【参考方案1】:

在 iOS7 中,Apple 发布了示例代码DateCell

演示表格单元格中日期对象的格式化显示以及使用 UIDatePicker 编辑这些值。 作为此表的委托,示例使用方法“didSelectRowAtIndexPath”打开 UIDatePicker 控件。

对于 iOS 6.x 及更早版本,UIViewAnimation 用于在屏幕上向上滑动 UIDatePicker 并在屏幕外向下滑动。对于 iOS 7.x,UIDatePicker 被内嵌添加到表格视图中。

UIDatePicker的action方法会直接设置自定义表格单元格的NSDate属性。此外,该示例还展示了如何使用 NSDateFormatter 类来实现自定义单元格的日期格式外观。

您可以在这里下载示例代码:DateCell。

【讨论】:

苹果的代码有问题。如果您想保留静态 tableView,请参阅下面的答案 @AaronBratcher 我只是在我的回答中介绍了 Datecell,你永远不会期望得到你想要的确切代码。您必须按照您的要求进行修改和更改。您的解决方案也不错,但请记住,您永远无法从您需要的其他代码中得到确切的信息。 最可怕的示例代码。他们可以就何时从 Code Complete 创建方法提出一些建议 哇,Apple 代码是......好吧,可以说重点是表格视图效果。我希望没有人从这个示例项目中的代码中得到启发:s【参考方案2】:

您可以使用我之前在下面给出的答案,或者使用我在 Swift 中制作的这个新类,以使这项任务变得很多更简单、更干净:https://github.com/AaronBratcher/TableViewHelper


我发现 Apple 提供的代码在几个方面存在问题:

您不能使用静态 tableView,因为它们使用的是 tableView:cellForRowAtIndexPath 方法 如果您在最后一个日期选择器单元格下方没有其他行,则代码会崩溃

对于静态单元格表​​,我在日期显示单元格下方定义了日期选择器单元格,并有一个标志来标识我是否正在编辑它。如果是,则返回适当的单元格高度,否则返回单元格高度为零。

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
    if (indexPath.section == 0 && indexPath.row == 2)  // this is my picker cell
        if (editingStartTime) 
            return 219;
         else 
            return 0;
        
     else 
        return self.tableView.rowHeight;
    

当点击显示日期的行时,我更改标志并执行更新动画以显示选择器。

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    if (indexPath.section == 0 && indexPath.row == 1)  // this is my date cell above the picker cell
        editingStartTime = !editingStartTime;
        [UIView animateWithDuration:.4 animations:^
            [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:2 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView reloadData];
        ];
    

如果我在同一个表中有多个日期/时间选择器,我会在点击时相应地设置标志并重新加载相应的行。我发现我可以保留我的静态表,使用更少的代码,并且更容易理解正在发生的事情。

【讨论】:

这对我有用,除了 UITableView 中似乎存在错误。在我的方法中正确返回了行高,但它实际上切换了我想要的相反高度。如果我重新加载了两次行,它就起作用了。 (我没有使用 tableView reloadData 因为我不想重新加载整个东西)。动画块也不是必需的,它似乎可以自己制作动画。 有没有人使用该示例创建文本选择器?如果是这样,如何?谢谢 您的意思是显示一行以便用户可以输入文本而不是选择日期?如果是这样,代码是相同的。只是显示行的内容不同。 我们在 iOS7.1 中出现了一个错误,它显示了单元格边界之外的对象——比如高度为 0 和内部选择器的对象。解决方案是为单元格获取一个出口并设置 cell.clipsToBounds = YES; @Dunken - 上面的评论中描述了一个解决方案:***.com/questions/18973573/… 即使行的高度为零,默认情况下内容不会被剪裁,因此您可以看到它们在下一行下方。【参考方案3】:

使用情节提要和静态表格,我能够使用以下代码获得相同的结果。这是一个很好的解决方案,因为如果您有许多形状奇特的单元格或想要动态显示/隐藏多个单元格,此代码仍然可以工作。

@interface StaticTableViewController: UITableViewController

@property (weak, nonatomic) IBOutlet UITableViewCell *dateTitleCell; // cell that will open the date picker. This is linked from the story board
@property (nonatomic, assign, getter = isDateOpen) BOOL dateOpen;

@end


@implementation StaticTableViewController

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

    // This is the index path of the date picker cell in the static table
    if (indexPath.section == 1 && indexPath.row == 1 && !self.isDateOpen)
        return 0;
    
    return [super tableView:tableView heightForRowAtIndexPath:indexPath];


-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
    [tableView beginUpdates];
    if (cell == self.dateTitleCell)
        self.dateOpen = !self.isDateOpen;
    
    [tableView reloadData];
    [self.tableView endUpdates];

【讨论】:

这里还有什么遗漏吗?单元格的高度没有改变:) 从 iOS 7.1 开始,您还必须在属性检查器中选择“剪辑到子视图”——这就是我所缺少的 :) 另外,行“self.dateOpen = !self.isDateOpen;”应该在开头阅读“self.isDateOpen =”,而不是“self.dateOpen =” 不需要[tableView reloadData]; 调用。目前它禁用行选择,但最好像这样取消选择行:[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES]; 我有奇怪的动画效果,比如日期单元格在“打开”后会是空白的,但是使用 begin 和 endupdates 解决了这个问题。现在很好很顺利。谢谢 datinc!【参考方案4】:

我从 Apple 获取了 DateCell 源,并删除了情节提要文件。

如果您想要没有情节提要的,请查看: https://github.com/ajaygautam/DateCellWithoutStoryboard

【讨论】:

感谢@Ajay,我使用了您修改后的代码,并希望将UIDatePicker 替换为UIPickerView。我尝试了一些东西并且能够在每个单元格上显示pickerView,但它不会随每个单元格更新。我已经发布了我的问题和代码here。请看一下,如果您能建议我一个解决方案,那将是非常友好的。 我看到了你的问题......它有太多的信息,并没有真正解释太多。也许你可以上传你的代码/压缩在某个地方让我看看。我可以调试它 - 如果我可以运行代码... 谢谢,我设法用UIPickerView 替换了UIDatePicker,但有几个错误。 1.打开UIPickerView并滚动表格时崩溃。 2. 当值被分配给顶部行的详细信息标签时,它会自动将值分配给表格底部行的UILabel详细信息。 Here is my code 你能找到testProject吗,运气好吗?? 抱歉,我有点忙。还需要这方面的帮助吗?【参考方案5】:

关于这方面的最佳教程之一是iOS 7 in-line UIDatePicker – Part 2。基本上在这里我使用静态表格视图单元并实现一些额外的方法。我为此使用了 Xamarin 和 C#:

你必须激活Clip Subviews

设置高度:

public override float GetHeightForRow (UITableView tableView, NSIndexPath indexPath)

    if (indexPath.Row == 4) 
        return (datePickerIsShowing) ? 206f : 0.0f;
    

    return base.GetHeightForRow(tableView,indexPath);

比类变量:private bool datePickerIsShowing = false;

显示日期选择器:

private void showDatePickerCell()
    datePickerIsShowing = true;
    this.TableView.BeginUpdates ();
    this.TableView.EndUpdates ();
    this.datePicker.Hidden = false;
    this.datePicker.Alpha = 0.0f;

    UIView.Animate (0.25, animation:
        () => 
            this.datePicker.Alpha = 1.0f;
        
    );
 

隐藏日期选择器:

private void hideDatePickerCell()
    datePickerIsShowing = false;
    this.TableView.BeginUpdates ();
    this.TableView.EndUpdates ();

    UIView.Animate (0.25,
        animation: () => 
            this.datePicker.Alpha = 0.0f;
        ,
        completion: () => 
            this.datePicker.Hidden = true;
        
    );
 

并调用此函数:

public override void RowSelected (UITableView tableView, NSIndexPath indexPath)

    if (indexPath.Row == 3) 
        if (datePickerIsShowing) 
            hideDatePickerCell ();
         else 
            showDatePickerCell ();
        
    

    this.TableView.DeselectRow (indexPath, true);

【讨论】:

如果您投反对票,也许您可​​以解释为什么投反对票。除了发布网站链接之外,我还包含了一些代码。就我而言,它是 C#。不知道有什么问题。【参考方案6】:

我制作了自己的自定义视图控制器,以简化在 tableview 中添加内联选择器的过程。您只需对它进行子类化并遵循一些简单的规则,它就会处理日期选择器的呈现。

您可以在此处找到它以及演示如何使用它的示例项目: https://github.com/ale84/ALEInlineDatePickerViewController

【讨论】:

【参考方案7】:

我在苹果的 datecell 示例中找到了一个缺陷的答案,在该示例中,您必须在最后一个 datecell 下方有一行,否则会出现错误。在 CellForRowAtIndexPath 方法中,将 ItemData 行替换为

NSArray *itemsArray = [self.dataArray objectAtIndex:indexPath.section];
NSDictionary *itemData = nil;

if(![indexPath isEqual:self.datePickerIndexPath])
    itemData = [itemsArray objectAtIndex:modelRow];

替换示例代码后,我现在可以显示 datePicker 单元格,而其下方没有单元格。

我刚刚加入了 ***,所以如果这是在错误的地方或其他地方,我深表歉意。

【讨论】:

【参考方案8】:

Aaron Bratcher 的答案是有效的,除非与多个部分一起使用。动画有点断断续续,并且没有很好地向下滑动下一部分。为了解决这个问题,我遍历了下一组部分,并将行向下平移了与日期选择器高度相同的量。

我将 didSelectRowAtIndexPath 编辑为:

// Return Data to delegate: either way is fine, although passing back the object may be more efficient
// [_delegate imageSelected:currentRecord.image withTitle:currentRecord.title withCreator:currentRecord.creator];
// [_delegate animalSelected:currentRecord];
if (indexPath.section == 1 && indexPath.row == 0)  // this is my date cell above the picker cell
    editingStartTime = !editingStartTime;
    [UIView animateWithDuration:.4 animations:^
        int height = 0;
        if (editingStartTime) 
            height = 162;
        
        UITableViewCell* temp = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]];
        [temp setFrame:CGRectMake(temp.frame.origin.x, temp.frame.origin.y, temp.frame.size.width, height)];
        for (int x = 2; x < [tableView numberOfSections]; x++) 
            for (int y = 0; y < [tableView numberOfRowsInSection:x]; y++) 
                UITableViewCell* temp = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:y inSection:x]];
                int y_coord = temp.frame.origin.y-162;
                if (editingStartTime) 
                    y_coord = temp.frame.origin.y+162;
                
                [temp setFrame:CGRectMake(temp.frame.origin.x, y_coord, temp.frame.size.width, temp.frame.size.height)];
            
        
    completion:^(BOOL finished)
        [self.tableView reloadData];
    ];

【讨论】:

谢谢@Timmahh,我也发现部分动画不连贯。我在我的第一个 Swift 应用程序中成功使用了您的解决方案!我发现 cellForRowAtIndexPath 在单元格不在屏幕的地方返回 nil 。为了避免这种情况,我添加了一个包含我的所有单元格的 IB 出口集合,这些单元格位于选取器单元格之后,并使用新的 y_coord 遍历它们。这似乎不灵活,因为我必须在添加新单元格时使集合保持最新。 你是对的。事实上,我已经解决了这个问题,但是堆栈溢出不允许我编辑我放在那里的代码。【参考方案9】:

添加到之前的答案,

我尝试了@datinc 和@Aaron Bratcher 解决方案,两者都运行良好,但在分组静态tableView 中动画不是那么干净。

玩了一会儿之后,我得到了这段代码,它对我来说既干净又好 -

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
    if (indexPath.section == 0 && indexPath.row == 1)
    
        if (self.isPickerOpened)
        
            return 162;
        
        else
        
            return 0;
        
    
    else
    
        return [super tableView:tableView heightForRowAtIndexPath:indexPath];
    


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    if (indexPath.section == 0 && indexPath.row == 0) 
        [tableView beginUpdates];
        self.isPickerOpened = ! self.isPickerOpened;
        [super tableView:tableView heightForRowAtIndexPath:indexPath];
        [self.tableView endUpdates];
    

主要的变化是使用-

        [super tableView:tableView heightForRowAtIndexPath:indexPath];

要更新行,这样表格的其余部分和单元格就没有动画了。

希望对某人有所帮助。

沙尼

【讨论】:

这帮助很大;谢谢!特别是与 Aaron Bratcher 的帖子捆绑在一起的 [super tableView] 方面,为我提供了在 iOS 9.2 上所需的结果。再次感谢您!【参考方案10】:

添加到以前的答案和@Aaron Bratcher 解决方案...

从 iOS 9 开始,我的动画就变得断断续续,而且表格需要一段时间才能加载,这已经够烦人的了。我将它缩小到日期选择器从情节提要加载缓慢的情况。以编程方式而不是在情节提要中添加选择器提高了加载性能,并且作为副产品,动画更流畅。

从情节提要中删除日期选择器并有一个空单元格,您可以按照之前的答案设置高度,然后在 viewDidLoad 上调用初始化:

- (void)initialiseDatePickers

    self.isEditingStartTime = NO;
    self.startTimePickerCell.clipsToBounds = YES;

    UIDatePicker *startTimePicker = [[UIDatePicker alloc] init];
    [startTimePicker addTarget:self action:@selector(startTimePickerChanged:) forControlEvents:UIControlEventValueChanged];
    [self.startTimePickerCell addSubview:startTimePicker];

然后执行操作,例如

- (IBAction)startTimePickerChanged:(id)sender

    NSLog(@"start time picker changed");

这比以前更快地加载表格。您还可以从 didSelectRowAtIndexPath 中删除动画线,因为没有它(ymmv)它的动画也很流畅。

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    if (indexPath.section == 0 && indexPath.row == 1)  // this is my date cell above the picker cell
        editingStartTime = !editingStartTime;
    

【讨论】:

【参考方案11】:

在没有动画的情况下使用 this answer 在 iOS 8.1 中可以正常工作。我已将其转换为以下 Swift:

import UIKit

class TableViewController: UITableViewController 

    var editingCell: Bool = false

    @IBOutlet weak var myCell: UITableViewCell!

    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 

        // Change the section and row to the title cell the user taps to reveal 
        // the cell below
        if (indexPath.section == 0 && indexPath.row == 2 && !editingCell) 
            return 0
         else 
            return self.tableView.rowHeight
        
    

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) 

        self.tableView.deselectRowAtIndexPath(indexPath, animated: false);

        var cell = tableView.cellForRowAtIndexPath(indexPath)

        self.tableView.beginUpdates()
        if (cell == self.myCell) 
            editingType = !editingType;
        
        self.tableView.endUpdates()
    

【讨论】:

【参考方案12】:

这是另一种解决问题的方法,无需静态常数。所有单元格都可以在静态和动态表视图中使用。此方法对标题和日期选择器使用单个单元格!

顺便说一句,您的表中可以有任意数量的日期选择器!

创建一个 UITableViewCell 子类:

您的所有表格视图单元格都必须从此类继承,并且您必须为每一行手动设置单元格高度。

//
//  CPTableViewCell.h
//
//  Copyright (c) CodePigeon. All rights reserved.
//

@class CPTableViewCell;

#define kUIAnimationDuration 0.33f

@protocol CPTableViewCellDelegate <NSObject>

@required
- (void)tableViewCellDidChangeValue:(CPTableViewCell *)cell;
@optional
- (void)tableViewCellDidBecomeFirstResponder:(CPTableViewCell *)cell;
- (void)tableViewCellResignedFirstResponder:(CPTableViewCell *)cell;
@end

@interface CPTableViewCell : UITableViewCell

@property (nonatomic, weak) IBOutlet UITableView *tableView;
@property (nonatomic, weak) IBOutlet CPTableViewCell *nextCell;
@property (nonatomic, weak) IBOutlet id<CPTableViewCellDelegate> delegate;

@property (nonatomic, copy) IBInspectable NSString *dataBindKey;
@property (nonatomic) IBInspectable CGFloat height;

@property (nonatomic, readonly) BOOL isFirstResponder;
@property (nonatomic) BOOL isEnabled;

- (void)commonInit;

- (id)value;
- (void)setValue:(id)value;

@end

//
//  CPTableViewCell.m
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTableViewCell.h"

@interface CPTableViewCell ()
@end

@implementation CPTableViewCell

- (instancetype)initWithFrame:(CGRect)frame

    self = [super initWithFrame:frame];

    if (!self)
        return nil;

    [self commonInit];

    return self;


- (instancetype)initWithCoder:(NSCoder *)aDecoder

    self = [super initWithCoder:aDecoder];

    if (!self)
        return nil;

    [self commonInit];

    return self;


- (void)commonInit

    _isFirstResponder = NO;
    _isEnabled = YES;


- (BOOL)canBecomeFirstResponder

    return _isEnabled;


- (BOOL)becomeFirstResponder

    if ([_delegate respondsToSelector:@selector(tableViewCellDidBecomeFirstResponder:)])
        [_delegate tableViewCellDidBecomeFirstResponder:self];

    return _isFirstResponder = YES;


- (BOOL)resignFirstResponder

    if (_isFirstResponder)
    
        if ([_delegate respondsToSelector:@selector(tableViewCellResignedFirstResponder:)])
            [_delegate tableViewCellResignedFirstResponder:self];

        _isFirstResponder = NO;
    

    return _isFirstResponder;


- (id)value

    [self doesNotRecognizeSelector:_cmd];

    return nil;


- (void)setValue:(id)value

    [self doesNotRecognizeSelector:_cmd];


@end

从我们的 CPTableViewCell 创建一个 CPDatePickerTableViewCell

//
//  CPDatePickerTableViewCell.h
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTableViewCell.h"

@interface CPDatePickerTableViewCell : CPTableViewCell

@property (nonatomic, copy) IBInspectable NSString *dateFormat;

@property (nonatomic, weak) IBOutlet UILabel *titleLabel;
@property (nonatomic, weak) IBOutlet UILabel *dateLabel;

@property (nonatomic, weak) IBOutlet UIDatePicker *datePicker;

@end

//
//  CPDatePickerTableViewCell.m
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPDatePickerTableViewCell.h"

#define kCPDatePickerTableViewCellPickerHeight 162.f

@interface CPDatePickerTableViewCell () <UITextFieldDelegate, UIPickerViewDelegate>

    NSDateFormatter *_dateFormatter;
    BOOL _isOpen;

@end

@implementation CPDatePickerTableViewCell

- (void)awakeFromNib

    [super awakeFromNib];

    _dateFormatter = [NSDateFormatter new];
    [_dateFormatter setDateFormat:_dateFormat];

    self.selectionStyle = UITableViewCellSelectionStyleNone;

    _dateLabel.text = [_dateFormatter stringFromDate:_datePicker.date];
    _datePicker.alpha = 0.f;
    _isOpen = NO;


- (BOOL)becomeFirstResponder

    if (_isOpen == NO)
    
        self.height += kCPDatePickerTableViewCellPickerHeight;
    
    else
    
        self.height -= kCPDatePickerTableViewCellPickerHeight;
    

    [UIView animateWithDuration:kUIAnimationDuration animations:^
        _datePicker.alpha = _isOpen ? 0.0f : 1.0f;
    ];

    [self.tableView beginUpdates];
    [self.tableView endUpdates];

    _isOpen = !_isOpen;

    [self.tableView endEditing:YES];

    return [super becomeFirstResponder];


- (BOOL)resignFirstResponder

    if (_isOpen == YES)
    
        self.height -= kCPDatePickerTableViewCellPickerHeight;

        [UIView animateWithDuration:kUIAnimationDuration animations:^
            _datePicker.alpha = 0.0f;
        ];

        [self.tableView beginUpdates];
        [self.tableView endUpdates];

        _isOpen = NO;
    

    return [super resignFirstResponder];


- (id)value

    return _datePicker.date;


- (void)setValue:(NSDate *)value

    _datePicker.date = value;
    _dateLabel.text = [_dateFormatter stringFromDate:_datePicker.date];


- (IBAction)datePickerValueChanged:(UIDatePicker *)sender

    [_dateLabel setText:[_dateFormatter stringFromDate:_datePicker.date]];

    [self.delegate tableViewCellDidChangeValue:self];


@end

在您的视图控制器中实现这两个委托方法

#pragma mark - UITableViewDelegate methods

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

    CPTableViewCell *cell = (CPTableViewCell *)[super tableView:tableView cellForRowAtIndexPath:indexPath];

    return [cell height];


- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath

    CPTableViewCell *cell = (CPTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];

    if ([cell canBecomeFirstResponder])
    
        [cell becomeFirstResponder];
    

    if (cell != _selectedCell)
    
        [_selectedCell resignFirstResponder];
    

    _selectedCell = cell;

    return YES;

如何在 Interface builder 中设置约束的示例

此外,我已经为 UITextFieldUITextView 编写了自定义单元格类,其中 tableView:didSelectRowAtIndexPath: 在选择单元格时被调用!

CPTextFieldTableViewCell

//
//  CPTextFieldTableViewCell.h
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTableViewCell.h"

@interface CPTextFieldTableViewCell : CPTableViewCell

@property (nonatomic, weak) IBOutlet UITextField *inputTextField;

@end

//
//  CPTextFieldTableViewCell.m
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTextFieldTableViewCell.h"

@interface CPTextFieldTableViewCell () <UITextFieldDelegate>
@end

@implementation CPTextFieldTableViewCell

- (void)awakeFromNib

    [super awakeFromNib];

    self.selectionStyle = UITableViewCellSelectionStyleNone;

    _inputTextField.userInteractionEnabled = NO;
    _inputTextField.delegate = self;


- (BOOL)becomeFirstResponder

    _inputTextField.userInteractionEnabled = YES;

    [_inputTextField becomeFirstResponder];

    return [super becomeFirstResponder];


- (BOOL)resignFirstResponder

    _inputTextField.userInteractionEnabled = NO;

    return [super resignFirstResponder];


- (void)setIsEnabled:(BOOL)isEnabled

    [super setIsEnabled:isEnabled];

    _inputTextField.enabled = isEnabled;


- (id)value

    return _inputTextField.text;


- (void)setValue:(NSString *)value

    _inputTextField.text = value;


#pragma mark - UITextFieldDelegate methods

- (void)textFieldDidEndEditing:(UITextField *)textField

    [self.delegate tableViewCellDidChangeValue:self];


@end

CBTextViewTableViewCell

单元格高度是动态的,当文本换行时行会增加!

//
//  CBTextViewTableViewCell.h
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTableViewCell.h"

@interface CPTextViewTableViewCell : CPTableViewCell

@property (nonatomic, weak) IBOutlet UITextView *inputTextView;

@end

//
//  CBTextViewTableViewCell.m
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTextViewTableViewCell.h"

@interface CPTextViewTableViewCell () <UITextViewDelegate>

    UITextView *_heightTextView;


@end

@implementation CPTextViewTableViewCell

@synthesize height = _height;

- (void)awakeFromNib

    [super awakeFromNib];

    self.selectionStyle = UITableViewCellSelectionStyleNone;

    _inputTextView.userInteractionEnabled = NO;
    _inputTextView.delegate = self;
    _inputTextView.contentInset = UIEdgeInsetsZero;
    _inputTextView.scrollEnabled = NO;


- (CGFloat)height

    if (!_heightTextView)
    
        CGRect frame = (CGRect) 
            .origin = CGPointMake(0.f, 0.f),
            .size = CGSizeMake(_inputTextView.textInputView.frame.size.width, 0.f)
        ;

        _heightTextView = [[UITextView alloc] initWithFrame:frame];
        _heightTextView.font = [UIFont systemFontOfSize:_inputTextView.font.pointSize];
        _heightTextView.textColor = UIColor.whiteColor;
        _heightTextView.contentInset = UIEdgeInsetsZero;
    

    _heightTextView.text = _inputTextView.text;

    CGSize size = [_heightTextView sizeThatFits:CGSizeMake(_inputTextView.textInputView.frame.size.width, FLT_MAX)];

    return size.height > _height ? size.height + _inputTextView.font.pointSize : _height;


- (BOOL)becomeFirstResponder

    _inputTextView.userInteractionEnabled = YES;

    [_inputTextView becomeFirstResponder];

    return [super becomeFirstResponder];


- (BOOL)resignFirstResponder

    _inputTextView.userInteractionEnabled = NO;

    return [super resignFirstResponder];


- (void)setIsEnabled:(BOOL)isEnabled

    [super setIsEnabled:isEnabled];

    _inputTextView.editable = isEnabled;


- (id)value

    return _inputTextView.text;


- (void)setValue:(NSString *)value

    _inputTextView.text = value;

    [_inputTextView setNeedsLayout];
    [_inputTextView layoutIfNeeded];


#pragma mark - UITextViewDelegate methods

- (void)textViewDidChange:(UITextView *)textView

    [self.delegate tableViewCellDidChangeValue:self];

    [self.tableView beginUpdates];
    [self.tableView endUpdates];


@end

【讨论】:

【参考方案13】:

在 Swift 版本中使用 DateCell 的最简单方法: 使用this example。

    打开这个例子并测试它(Make Xcode to Convert to Swift 2)

    将“DateCellTableViewController.swift”类拖到您的项目中。

    打开“Main.storyboard”并复制“DateCell” ViewController 对象并将其粘贴到您的故事板中。

【讨论】:

以上是关于iOS 7 - 如何在表格视图中显示日期选择器?的主要内容,如果未能解决你的问题,请参考以下文章

如何在日期选择器中设置日期限制

如何在日期选择器对话框中设置日期限制

选择表格单元格以显示 iOS7 上的新视图崩溃,“无法识别的选择器发送到实例”

点击文本字段时用选择器视图替换键盘(Swift、Storyboard、iOS 9、Xcode 7)

如何将 Javascript 日期转换为 iOS 日期格式

如何在iOS swift中实现带有月份、日期和时间的自定义选择器?