Вопрос по uidatepicker, swift, uitableview, ios7, datecell – iOS 7 - Как отобразить средство выбора даты в виде таблицы?

118

В видео WWDC 2013 Apple предлагает отображать средство выбора на месте в табличном представлении в iOS 7. Как вставить и анимировать представление между ячейками табличного представления?

Вот так из приложения Apple Calendar:

Пожалуйста, проверьте:Самый простой способ использовать DateCell в Swift Ahmed Lotfy
Какое видео WWDC это? Я'Я пытаюсь понять, почему это специфично для iOS7, и если есть причина, почему это нельзя было сделать в более ранних версиях. Clafou
Нашел, это "Какие's Новое в дизайне пользовательского интерфейса iOS » (спасибо ASCIIwwdc). Обоснование заключается в том, что старый стиль неВыглядит прямо в линию, но новый плоский вид. Clafou

Ваш Ответ

13   ответов
3

чтобы упростить процесс добавления встроенного средства выбора в виде таблицы. Вы просто создаете подкласс и следуйте некоторым простым правилам, и он обрабатывает презентацию выбора даты.

Вы можете найти его здесь вместе с примером проекта, который демонстрирует, как его использовать:https://github.com/ale84/ALEInlineDatePickerViewController

1

С помощьюэтот ответ без анимации работает корректно в 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()
    }
}
3

когда у вас должна быть строка ниже последней, или вы получите ошибку. В методе CellForRowAtIndexPath замените строку ItemData на

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

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

После замены примера кода теперь я могу отображать отображение ячейки datePicker без ячейки под ней.

Я только что присоединился к stackoverflow, поэтому, если это не в том месте или где-то еще, я прошу прощения.

84

который я ранее дал ниже, или использовать этот новый класс в 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];
        }];
    }
}

Если в одной и той же таблице несколько указателей даты / времени, я соответствующим образом устанавливаю флаги для щелчка и перезагружаю соответствующие строки. Я'Я обнаружил, что я могу хранить свою статическую таблицу, использовать намного меньше кода, и мне легче понять, что происходит.

Там есть ошибка с iOS7.1, которая показывает объекты за пределами ячеек - например, с высотой 0 и пикапом внутри. Решение состоит в том, чтобы получить выход для ячейки и установить cell.clipsToBounds = YES; EmilDo
Единственная проблема здесь в том, что это не работает ниже ios7 Craig Moore
Я попробовал вызовы beginUpdates / endUpdates вместо UIView animateWithDuration и обнаружил, что это не так.т надежный. Aaron Bratcher
Перезаписать блок анимации UIView с помощью этого: [tableView beginUpdates]; [tableView endUpdates]; // более простое решение budidino
3

Я попробовал оба решения: @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];

чтобы обновить строку, таким образом, остальные разделы таблицы и ячейки не анимируются.

Надеюсь, это кому-нибудь поможет.

Шани

Это очень помогло; благодарю вас! В частности, аспект [super tableView], в комплекте с Аароном Братчеромпост, принес мне результаты, которые мне нужны на iOS 9.2. Еще раз спасибо! Terrance Shaw
5

Если вы хотите один без раскадровки, взгляните на:https://github.com/ajaygautam/DateCellWithoutStoryboard

Вы можете найти тестовый проект, Удачи? Mughees Musaddiq
Извините, я немного занят. Все еще нужна помощь с этим? Ajay Gautam
Я видел ваш вопрос ... в нем слишком много информации, и он неэто действительно многое объясняет. Возможно, вы можете загрузить свой код / заархивировать куда-нибудь, чтобы я посмотрел. Я могу отладить его - если я могу запустить код ... Ajay Gautam
Спасибо @Ajay, я использовал ваш исправленный код и хочу заменитьUIDatePicker сUIPickerView, Я попробовал немного вещей и смог показатьpickerView на каждой клетке, но это не такT обновляется с каждой ячейкой. Я разместил свой вопрос и кодВот, Пожалуйста, посмотрите, и было бы очень любезно, если бы вы могли предложить мне решение. Mughees Musaddiq
18

я смог достичь того же результата, используя следующий код. Это отличное решение, потому что если у вас много ячеек странной формы или вы хотите иметь несколько ячеек, которые динамически отображаются / скрываются, этот код все равно будет работать.

@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];
}
Также линия "self.dateOpen =! self.isDateOpen; " должен прочесть "self.isDateOpen = " в начале нетself.dateOpen = " Peter Johnson
[tableView reloadData]; звонок не требуется. В настоящее время он отключает выбор строки, но лучше отменить выбор строки следующим образом:[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES]; Barry Haanstra
здесь чего-то еще не хватает? Высота ячеек не меняется :) DevC
У меня были странные анимационные эффекты, вроде того, что после даты ячейка будет пустойоткрытие» но, используя начало и конец, решил это. Красиво и гладко сейчас. Спасибо, Датин! nh32rg
Начиная с iOS 7.1 вы также должны выбратьКлип для SubViews " в инспекторе Атрибутов - вот чего мне не хватало :) DevC
101

DateCell

Демонстрирует форматированное отображение объектов даты в ячейках таблицы и использование UIDatePicker для редактирования этих значений. В качестве делегата этой таблицы в примере используется метод "didSelectRowAtIndexPath» открыть элемент управления UIDatePicker.

Для iOS 6.x и более ранних версий UIViewAnimation используется для перемещения UIDatePicker вверх по экрану и вниз за экран. Для iOS 7.x UIDatePicker добавляется в строку в табличное представление.

Метод действия UIDatePicker непосредственно устанавливает свойство NSDate ячейки пользовательской таблицы. Кроме того, этот пример показывает, как использовать класс NSDateFormatter для создания пользовательской ячейки.s дата в формате.

Вы можете скачать образец кода здесь:DateCell.

@AaronBratcher я просто представляюDatecell в моем ответе, и вы никогда не ожидаете, что получите точный код, который вы хотите. Вы должны изменить и изменить в соответствии с вашими требованиями. Ваше решение также хорошо, но помните, что вы никогда не получите точные данные из другого кода, который вам требуется. Nitin Gohel
Ух ты, код Apple ... ну, скажем так, основное внимание уделяется эффекту табличного представления. Я надеюсь, что никто не вдохновится их кодом в этом примере проекта: s Daniel
Яблоко'С кодом есть проблемы. Смотрите мой ответ ниже, если вы хотите сохранить свой статический tableView Aaron Bratcher
самый ужасный пример кода. Они могли бы сделать несколько советов о том, когда создавать метод из Code Complete. Anirudha Agashe
0

использоватьэтот пример.

Откройте этот пример и протестируйте его (сделать Xcode для преобразования в Swift 2)

Тащить, тянуть "DateCellTableViewController.swift» класс для вашего проекта.

Открыто "Main.storyboard» и копироватьDateCell» Объект ViewController и вставьте его в свою раскадровку.

2

Начиная с 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;
    }
}
5

встроенный UIDatePicker для iOS 7 - Часть 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 #. Дон»не знаю чтос этим не так. testing
3

за исключением случаев, когда он использовался с несколькими разделами. Анимации были немного изменчивыми, и это неСледующие разделы очень хорошо сдвигаются вниз. Чтобы исправить это, я перебрал следующий набор разделов и перевел строки на ту же сумму, что и средство выбора даты.высота

Я отредактировал 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];
    }];
}
Отличный ответ! Решить все мои проблемы, спасибо много! MichiZH
Вы'верно. На самом деле, я исправил проблему, но переполнение стека неПозвольте мне отредактировать код, который я там поместил. Timothy Logan
Спасибо @Timmahh, я нашел анимацию раздела тоже нестабильной. Я успешно использовал ваше решение в своем первом приложении Swift! Я обнаружил, что cellForRowAtIndexPath возвращает ноль, где ячейки находятся вне экрана. Чтобы избежать этого, я добавил коллекцию аутлетов IB, содержащую все мои ячейки, которые следовали за ячейкой сборщика, и прошел через них с вашей новой y_coord. Это кажется негибким, поскольку я должен постоянно обновлять коллекцию, когда добавляю новые ячейки. Josh
1

Все ячейки могут использоваться в статических и динамических табличных представлениях. Этот метод использует одну ячейку для выбора заголовка и даты!

Кстати, вы можете иметь столько сборщиков дат на вашем столе, сколько пожелаете!

Создать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
</cptableviewcelldelegate></nsobject>

СоздатьCPDatePickerTableViewCell класс из нашего CPTableViewCell

//
//  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
</uitextfielddelegate,>

По вашему мнению, контроллер реализует эти два метода делегата

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

Пример, как установить ограничения в Интерфейсном Разработчике

Кроме того, я написал пользовательские классы ячеек дляUITextField а такжеUITextView где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
</uitextfielddelegate>

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

Похожие вопросы