У відеозаписі WWDC 2013 компанія Apple пропонує відобразити місце вибору на вікні таблиці в iOS 7. Як вставити та анімувати представлення даних між клітинками подання таблиці?
Ось так, з програми календаря Apple:
У відеозаписі WWDC 2013 компанія Apple пропонує відобразити місце вибору на вікні таблиці в iOS 7. Як вставити та анімувати представлення даних між клітинками подання таблиці?
Ось так, з програми календаря Apple:
Відповіді:
З iOS7 Apple випустила зразок коду DateCell
.
Демонструє відформатоване відображення об'єктів дати у комірках таблиці та використання UIDatePicker для редагування цих значень. Як делегат цієї таблиці, зразок використовує метод "didSelectRowAtIndexPath" для відкриття елемента UIDatePicker.
Для iOS 6.x та новіших версій UIViewAnimation використовується для переміщення UIDatePicker вгору по екрану та вниз по екрану. Для iOS 7.x, UIDatePicker додається рядково до подання таблиці.
Метод дії UIDatePicker безпосередньо встановить властивість NSDate клітинки користувацької таблиці. Крім того, в цьому зразку показано, як використовувати клас NSDateFormatter для досягнення зовнішнього вигляду у форматі даної клітинки.
Ви можете завантажити зразок коду тут: DateCell .
Ви можете скористатися відповіддю, яку я раніше наводив нижче, або використати цей новий клас у Swift, який я зробив, щоб зробити це завдання набагато простішим та чистішим: https://github.com/AaronBratcher/TableViewHelper
Я вважаю код, наданий Apple, проблематичним двома способами:
Для таблиць статичних комірок я визначаю клітинку вибору дати під коміркою відображення дати і прапор, який ідентифікує, чи редагую її. Якщо я є, я повертаю відповідну висоту комірки, інакше повертаю висоту комірки нульову.
- (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];
}];
}
}
Якщо у мене в одній таблиці є декілька інструментів вибору дати / часу, я встановлюю прапори відповідно до клацання і перезавантажую відповідні рядки. Я виявив, що я можу зберігати свою статичну таблицю, використовувати набагато менше коду, і простіше зрозуміти, що відбувається.
Використовуючи табло та статичну таблицю, я зміг досягти такого ж результату, використовуючи наступний код. Це відмінне рішення, тому що якщо у вас багато комірок дивної форми або хочете мати декілька комірок, які динамічно показані / приховані, цей код все одно буде працювати.
@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];
}
[tableView reloadData];
Виклик не потрібно. Наразі це вимкнення вибору рядків, але краще скасувати виділення рядка таким чином:[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
Я взяв джерело DateCell з Apple і видалив файл розкадровки.
Якщо ви хочете, щоб він не мав розповідь, подивіться на сторінку: https://github.com/ajaygautam/DateCellWithoutStoryboard
UIDatePicker
з UIPickerView
. Я спробував декілька речей і міг показати їх pickerView
у кожній комірці, але вона не оновлюється з кожною коміркою. Я відправив своє питання і коди тут . Погляньте, і було б дуже люб'язно, якби ви могли запропонувати мені рішення.
UIDatePicker
з , UIPickerView
але з кількома помилками. 1. Він виходить з ладу, коли ви відкриваєте UIPickerView
та прокручуєте таблицю. 2. Він автоматично присвоює значення UILabel
Detail у нижчих рядках таблиці, коли значення присвоюються мітці Details у верхніх рядках. Ось мій код
Один з найкращих навчальних посібників з цього приводу - iOS 7, вбудований 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);
}
Я створив власний власний контролер подання, щоб спростити процес додавання вибору вбудованого вбудованого рядка у вигляді таблиці. Ви просто підкласируєте його та дотримуєтесь простих правил, і він обробляє презентацію вибору дати.
Ви можете знайти його тут разом із прикладом проекту, який демонструє, як ним користуватися: https://github.com/ale84/ALEInlineDatePickerViewController
У прикладі datecell яблука я знайшов відповідь на дефект, у якому ви повинні мати рядок нижче останньої datecell або ви отримаєте помилку. У методі CellForRowAtIndexPath замініть рядок ItemData на
NSArray *itemsArray = [self.dataArray objectAtIndex:indexPath.section];
NSDictionary *itemData = nil;
if(![indexPath isEqual:self.datePickerIndexPath])
itemData = [itemsArray objectAtIndex:modelRow];
Після заміни зразкового коду тепер я можу відобразити відображення комірки datePicker, не маючи комірки під нею.
Я щойно приєднався до stackoverflow, тому якщо це не в тому місці чи десь ще, я вибачаюся.
Відповідь Аарона Братчера спрацювала, за винятком випадків, коли вони використовувались у кількох розділах. Анімація була трохи похмурою, і вона не ковзала наступними розділами вниз дуже добре. Щоб виправити це, я повторив наступний набір розділів і переклав рядки вниз на ту ж суму, що і висота вибору дати.
Я редагував 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];
}];
}
Додавши до попередніх відповідей,
Я спробував і рішення @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 ...
З 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;
}
}
Використання цієї відповіді без анімації працює правильно в 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()
}
}
Ось ще один спосіб вирішити задачу без статичних постійних чисел. Усі комірки можуть використовуватися у статичних та динамічних поданнях таблиць. Цей метод використовує одну клітинку як для вибору назви, так і для дати!
Тим не менш, у твоєму столі може бути стільки вибраних дат!
Створіть підклас 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
Створіть клас 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
На ваш погляд, контролер реалізує ці два способи делегування
#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
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
Найпростіший спосіб використання DateCell у версії Swift: Використовуйте цей приклад .
Перетягніть клас " DateCellTableViewController.swift " до свого проекту.
Відкрийте "Main.storyboard" та скопіюйте " DateCell " ViewController Object та вставте її у свою таблицю розкад.