У мене є UITableView, що в деяких випадках законно бути порожнім. Тому замість показу фонового зображення програми я вважаю за краще надрукувати дружнє повідомлення на екрані, наприклад:
Цей список тепер порожній
Який найпростіший спосіб це зробити?
У мене є UITableView, що в деяких випадках законно бути порожнім. Тому замість показу фонового зображення програми я вважаю за краще надрукувати дружнє повідомлення на екрані, наприклад:
Цей список тепер порожній
Який найпростіший спосіб це зробити?
Відповіді:
Властивість backgroundView UITableView - ваш друг.
В viewDidLoad будь-якому місці, де reloadDataвам слід визначити, чи є ваша таблиця порожнім чи ні, і оновіть властивість backgroundView UITableView за допомогою UIView, що містить UILabel, або просто встановіть його на нуль. Це воно.
Звичайно, можна змусити джерело даних UITableView виконувати подвійний обов'язок і повертати спеціальну клітинку "список порожній", це сприймає мене як хитрощі. Раптом numberOfRowsInSection:(NSInteger)sectionдоводиться обчислювати кількість рядків інших розділів, про які не запитували, щоб переконатися, що вони теж порожні. Вам також потрібно зробити спеціальну комірку, яка містить порожнє повідомлення. Також не забувайте, що вам потрібно, ймовірно, змінити висоту своєї комірки, щоб вмістити порожнє повідомлення. Це все можливо, але здається, що це допомога на вершині верхньої групи.
backgroundViewприховану власність - це шлях. З DZNEmptyDataSet, ми повинні використовувати йогоemptyDataSetSource
tableView.backgroundView!.userInteraction = trueпісля рядка, який ви встановили tableView.backgroundView = constructMyViewWithButtons(), або як би ви його встановили.
Те саме, що відповідь Джонстона, але я вважав за краще це продовження:
import UIKit
extension UITableView {
func setEmptyMessage(_ message: String) {
let messageLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.bounds.size.height))
messageLabel.text = message
messageLabel.textColor = .black
messageLabel.numberOfLines = 0
messageLabel.textAlignment = .center
messageLabel.font = UIFont(name: "TrebuchetMS", size: 15)
messageLabel.sizeToFit()
self.backgroundView = messageLabel
self.separatorStyle = .none
}
func restore() {
self.backgroundView = nil
self.separatorStyle = .singleLine
}
}
Використання:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if things.count == 0 {
self.tableView.setEmptyMessage("My Message")
} else {
self.tableView.restore()
}
return things.count
}
func numberOfSections(in tableView: UITableView) -> Intметод
Виходячи з відповідей тут, ось короткий клас, який я склав, і який ви можете використовувати у своєму UITableViewController.
import Foundation
import UIKit
class TableViewHelper {
class func EmptyMessage(message:String, viewController:UITableViewController) {
let rect = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: self.view.bounds.size.width, height: self.view.bounds.size.height))
let messageLabel = UILabel(frame: rect)
messageLabel.text = message
messageLabel.textColor = UIColor.blackColor()
messageLabel.numberOfLines = 0;
messageLabel.textAlignment = .Center;
messageLabel.font = UIFont(name: "TrebuchetMS", size: 15)
messageLabel.sizeToFit()
viewController.tableView.backgroundView = messageLabel;
viewController.tableView.separatorStyle = .None;
}
}
У ваших UITableViewControllerви можете назвати цеnumberOfSectionsInTableView(tableView: UITableView) -> Int
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if projects.count > 0 {
return 1
} else {
TableViewHelper.EmptyMessage("You don't have any projects yet.\nYou can create up to 10.", viewController: self)
return 0
}
}
За невеликої допомоги від http://www.appcoda.com/pull-to-refresh-uitableview-empty/
viewController.tableView.separatorStyle = .noneне потрібно.
Я рекомендую таку бібліотеку: DZNEmptyDataSet
Найпростіший спосіб додати його у свій проект - це використовувати його з кокаоподами так: pod 'DZNEmptyDataSet'
У свій TableViewController додайте наступне твердження про імпорт (Swift):
import DZNEmptyDataSet
Потім переконайтеся , що ваш клас відповідає вимогам DNZEmptyDataSetSourceі , DZNEmptyDataSetDelegateяк так:
class MyTableViewController: UITableViewController, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate
У ваших viewDidLoadдодайте наступні рядки коду:
tableView.emptyDataSetSource = self
tableView.emptyDataSetDelegate = self
tableView.tableFooterView = UIView()
Тепер все, що вам потрібно зробити, щоб показати порожній стан, це:
//Add title for empty dataset
func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
let str = "Welcome"
let attrs = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)]
return NSAttributedString(string: str, attributes: attrs)
}
//Add description/subtitle on empty dataset
func descriptionForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
let str = "Tap the button below to add your first grokkleglob."
let attrs = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleBody)]
return NSAttributedString(string: str, attributes: attrs)
}
//Add your image
func imageForEmptyDataSet(scrollView: UIScrollView!) -> UIImage! {
return UIImage(named: "MYIMAGE")
}
//Add your button
func buttonTitleForEmptyDataSet(scrollView: UIScrollView!, forState state: UIControlState) -> NSAttributedString! {
let str = "Add Grokkleglob"
let attrs = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleCallout)]
return NSAttributedString(string: str, attributes: attrs)
}
//Add action for button
func emptyDataSetDidTapButton(scrollView: UIScrollView!) {
let ac = UIAlertController(title: "Button tapped!", message: nil, preferredStyle: .Alert)
ac.addAction(UIAlertAction(title: "Hurray", style: .Default, handler: nil))
presentViewController(ac, animated: true, completion: nil)
}
Ці методи не є обов'язковими, можливо також просто показати порожній стан без кнопки тощо.
Для Swift 4
// MARK: - Deal with the empty data set
// Add title for empty dataset
func title(forEmptyDataSet _: UIScrollView!) -> NSAttributedString! {
let str = "Welcome"
let attrs = [NSAttributedStringKey.font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.headline)]
return NSAttributedString(string: str, attributes: attrs)
}
// Add description/subtitle on empty dataset
func description(forEmptyDataSet _: UIScrollView!) -> NSAttributedString! {
let str = "Tap the button below to add your first grokkleglob."
let attrs = [NSAttributedStringKey.font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)]
return NSAttributedString(string: str, attributes: attrs)
}
// Add your image
func image(forEmptyDataSet _: UIScrollView!) -> UIImage! {
return UIImage(named: "MYIMAGE")
}
// Add your button
func buttonTitle(forEmptyDataSet _: UIScrollView!, for _: UIControlState) -> NSAttributedString! {
let str = "Add Grokkleglob"
let attrs = [NSAttributedStringKey.font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.callout), NSAttributedStringKey.foregroundColor: UIColor.white]
return NSAttributedString(string: str, attributes: attrs)
}
// Add action for button
func emptyDataSetDidTapButton(_: UIScrollView!) {
let ac = UIAlertController(title: "Button tapped!", message: nil, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Hurray", style: .default, handler: nil))
present(ac, animated: true, completion: nil)
}
Одним із способів цього буде модифікація джерела даних, щоб повернутись, 1коли кількість рядків дорівнює нулю, та створити в tableView:cellForRowAtIndexPath:методі спеціальну клітинку (можливо, з іншим ідентифікатором комірок) .
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger actualNumberOfRows = <calculate the actual number of rows>;
return (actualNumberOfRows == 0) ? 1 : actualNumberOfRows;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger actualNumberOfRows = <calculate the actual number of rows>;
if (actualNumberOfRows == 0) {
// Produce a special cell with the "list is now empty" message
}
// Produce the correct cell the usual way
...
}
Це може дещо ускладнитися, якщо у вас є кілька контролерів перегляду таблиць, які потрібно підтримувати, оскільки хтось з часом забуде вставити нульову перевірку. Кращий підхід - створити окрему реалізацію UITableViewDataSourceреалізації, яка завжди повертає один рядок з налагоджуваним повідомленням (назвемо це EmptyTableViewDataSource). Коли дані, якими керує ваш контролер перегляду таблиці, змінюються, код, який керує зміною, перевірятиме, чи дані порожні. Якщо він не порожній, встановіть контролер подання таблиці з його звичайним джерелом даних; в іншому випадку встановіть його з екземпляром того, EmptyTableViewDataSourceщо було налаштовано відповідним повідомленням.
deleteRowsAtIndexPaths:withRowAnimation:оскільки число, повернене з numberOfRowsInSectionпотреб, відповідає результату $ numRows - $ rowsDeleted.
Я використовую для цього повідомлення titleForFooterInSection. Я не знаю, чи це неоптимально чи ні, але це працює.
-(NSString*)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
NSString *message = @"";
NSInteger numberOfRowsInSection = [self tableView:self.tableView numberOfRowsInSection:section ];
if (numberOfRowsInSection == 0) {
message = @"This list is now empty";
}
return message;
}
return tableView.numberOfRowsInSection(section) == 0 ? "This list is now empty" : nil
Тож для більш безпечного рішення:
extension UITableView {
func setEmptyMessage(_ message: String) {
guard self.numberOfRows() == 0 else {
return
}
let messageLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.bounds.size.height))
messageLabel.text = message
messageLabel.textColor = .black
messageLabel.numberOfLines = 0;
messageLabel.textAlignment = .center;
messageLabel.font = UIFont.systemFont(ofSize: 14.0, weight: UIFontWeightMedium)
messageLabel.sizeToFit()
self.backgroundView = messageLabel;
self.separatorStyle = .none;
}
func restore() {
self.backgroundView = nil
self.separatorStyle = .singleLine
}
public func numberOfRows() -> Int {
var section = 0
var rowCount = 0
while section < numberOfSections {
rowCount += numberOfRows(inSection: section)
section += 1
}
return rowCount
}
}
і для UICollectionView:
extension UICollectionView {
func setEmptyMessage(_ message: String) {
guard self.numberOfItems() == 0 else {
return
}
let messageLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.bounds.size.height))
messageLabel.text = message
messageLabel.textColor = .black
messageLabel.numberOfLines = 0;
messageLabel.textAlignment = .center;
messageLabel.font = UIFont.systemFont(ofSize: 18.0, weight: UIFontWeightSemibold)
messageLabel.sizeToFit()
self.backgroundView = messageLabel;
}
func restore() {
self.backgroundView = nil
}
public func numberOfItems() -> Int {
var section = 0
var itemsCount = 0
while section < self.numberOfSections {
itemsCount += numberOfItems(inSection: section)
section += 1
}
return itemsCount
}
}
Більш загальне рішення:
protocol EmptyMessageViewType {
mutating func setEmptyMessage(_ message: String)
mutating func restore()
}
protocol ListViewType: EmptyMessageViewType where Self: UIView {
var backgroundView: UIView? { get set }
}
extension UITableView: ListViewType {}
extension UICollectionView: ListViewType {}
extension ListViewType {
mutating func setEmptyMessage(_ message: String) {
let messageLabel = UILabel(frame: CGRect(x: 0,
y: 0,
width: self.bounds.size.width,
height: self.bounds.size.height))
messageLabel.text = message
messageLabel.textColor = .black
messageLabel.numberOfLines = 0
messageLabel.textAlignment = .center
messageLabel.font = UIFont(name: "TrebuchetMS", size: 16)
messageLabel.sizeToFit()
backgroundView = messageLabel
}
mutating func restore() {
backgroundView = nil
}
}
Я можу лише порекомендувати перетягувати UITextView всередину TableView після комірок. Встановіть підключення до ViewController і при необхідності прихойте / відображіть його (наприклад, коли таблиця перезавантажується).
Використання backgroundView добре, але воно не прокручується так добре, як у Mail.app.
Я зробив щось подібне до того, що xtravar робив .
Я додав перегляд поза ієрархією перегляду tableViewController.

Тоді я використав наступний код у tableView:numberOfRowsInSection::
if someArray.count == 0 {
// Show Empty State View
self.tableView.addSubview(self.emptyStateView)
self.emptyStateView.center = self.view.center
self.emptyStateView.center.y -= 60 // rough calculation here
self.tableView.separatorColor = UIColor.clear
} else if self.emptyStateView.superview != nil {
// Empty State View is currently visible, but shouldn't
self.emptyStateView.removeFromSuperview()
self.tableView.separatorColor = nil
}
return someArray.count
В основному я додав emptyStateViewоб'єкт як підзагляд tableView. Оскільки роздільники перекриватимуть вигляд, я встановив їх колір clearColor. Щоб повернутися до кольору роздільника за замовчуванням, ви можете просто встановити його nil.
tableHeaderViewта переконайтесь, що він змінює розмір .
Використання контролера перегляду контейнерів - це правильний спосіб зробити це відповідно до Apple .
Я розміщую всі свої порожні погляди стану в окрему дошку розкадрувань. Кожен під власним підкласом UIViewController. Я додаю вміст безпосередньо під їх кореневим поданням. Якщо потрібні будь-які дії / кнопки, тепер у вас вже є контролер, який обробляє це.
Тоді справа лише в тому, щоб створити потрібний контролер подання з цієї дошки розкадри, додати його як дочірній контролер подання та додати перегляд контейнера до ієрархії tableView (підподання). Ваш порожній вигляд стану також буде прокручуватися, що почуває себе добре і дозволить вам реалізувати функцію "тягнути" для оновлення.
Прочитайте розділ "Додавання контролера подання даних до вашого вмісту", щоб дізнатися, як реалізувати.
Просто переконайтеся, що ви встановили дочірню рамку перегляду як,
(0, 0, tableView.frame.width, tableView.frame.height)і речі будуть зосереджені та вирівняні належним чином.
По-перше, проблеми з іншими популярними підходами.
BackgroundView
Перегляд фону не є гарним центром, якщо ви використовували простий випадок встановлення його на UILabel.
Осередки, заголовки або колонтитули для відображення повідомлення
Це втручається у ваш функціональний код та запроваджує дивні випадкові випадки. Якщо ви хочете ідеально центрувати своє повідомлення, це додає іншого рівня складності.
Прокат власного контролера подання таблиці
Ви втрачаєте вбудовану функціональність, таку як refreshControl, і знову винаходите колесо. Дотримуйтесь UITableViewController для отримання найкращих результатів.
Додавання UITableViewController як контролер дочірнього перегляду
У мене є відчуття, що у вас виникнуть проблеми з contentInset в iOS 7+ - плюс чому ускладнюєте речі?
Моє рішення
Найкраще рішення, яке я придумав (і, безумовно, це не ідеально) - зробити спеціальний вигляд, який може сидіти на вершині подання прокрутки і діяти відповідно. Це, очевидно, ускладнюється в iOS 7 з безумством contentInset, але це можливо.
Речі, на які слід стежити:
Після того, як ви це зрозуміли один раз в одному підкласі UIView, ви можете використовувати його для всього - завантаження спінерів, відключення представлень даних, показ повідомлень про помилки тощо.
addSubViewйого використовую, він додається до подання таблиці, який завжди створює проблеми з автоматичним компонуванням.
Це найкраще і просте рішення.
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 60)];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 60)];
label.text = @"This list is empty";
label.center = self.view.center;
label.textAlignment = NSTextAlignmentCenter;
[view addSubview:label];
self.tableView.backgroundView = view;
Показати Повідомлення для порожнього списку, Збільшити його UITableView або UICollectionView .
extension UIScrollView {
func showEmptyListMessage(_ message:String) {
let rect = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: self.bounds.size.width, height: self.bounds.size.height))
let messageLabel = UILabel(frame: rect)
messageLabel.text = message
messageLabel.textColor = .black
messageLabel.numberOfLines = 0
messageLabel.textAlignment = .center
messageLabel.font = UIFont.systemFont(ofSize: 15)
messageLabel.sizeToFit()
if let `self` = self as? UITableView {
self.backgroundView = messageLabel
self.separatorStyle = .none
} else if let `self` = self as? UICollectionView {
self.backgroundView = messageLabel
}
}
}
Використання:
if cellsViewModels.count == 0 {
self.tableView.showEmptyListMessage("No Product In List!")
}
АБО:
if cellsViewModels.count == 0 {
self.collectionView?.showEmptyListMessage("No Product In List!")
}
Пам'ятайте: не забудьте видалити мітку повідомлення, якщо дані з’являться після оновлення.
Виберіть сценарій tableviewController в сценарій
Перетягніть мітку UIView Add із своїм повідомленням (наприклад: Без даних)
створити розетку UIView (скажімо, наприклад, yournoDataView) на своєму TableViewController.
і в viewDidLoad
self.tableView.backgroundView = yourNoDataView
Використання Swift 4.2
func numberOfSections(in tableView: UITableView) -> Int
{
var numOfSections: Int = 0
if self.medArray.count > 0
{
tableView.separatorStyle = .singleLine
numOfSections = 1
tableView.backgroundView = nil
}
else
{
let noDataLabel: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: tableView.bounds.size.height))
noDataLabel.text = "No Medicine available.Press + to add New Pills "
noDataLabel.textColor = UIColor.black
noDataLabel.textAlignment = .center
tableView.backgroundView = noDataLabel
tableView.separatorStyle = .none
}
return numOfSections
}
Ви можете додати це до свого базового класу.
var messageLabel = UILabel()
func showNoDataMessage(msg: String) {
let rect = CGRect(origin: CGPoint(x: 0, y :self.view.center.y), size: CGSize(width: self.view.bounds.width - 16, height: 50.0))
messageLabel = UILabel(frame: rect)
messageLabel.center = self.view.center
messageLabel.text = msg
messageLabel.numberOfLines = 0
messageLabel.textColor = Colors.grayText
messageLabel.textAlignment = .center;
messageLabel.font = UIFont(name: "Lato-Regular", size: 17)
self.view.addSubview(messageLabel)
self.view.bringSubviewToFront(messageLabel)
}
Покажіть це так у класі на отриманні даних з api.
func populateData(dataSource : [PRNJobDataSource]){
self.dataSource = dataSource
self.tblView.reloadData()
if self.dataSource.count == 0 {self.showNoDataMessage(msg: "No data found.")}
}
Сховай це так.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.dataSource.count > 0 {self.hideNoDataMessage()}
return dataSource.count
}
func hideNoDataMessage(){
messageLabel.removeFromSuperview()
}
Швидка версія, але краща та простіша форма. ** 3.0
Я сподіваюся, що це сервер вашої мети ......
У вашому UITableViewController.
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.isActive && searchController.searchBar.text != "" {
if filteredContacts.count > 0 {
self.tableView.backgroundView = .none;
return filteredContacts.count
} else {
Helper.EmptyMessage(message: ConstantMap.NO_CONTACT_FOUND, viewController: self)
return 0
}
} else {
if contacts.count > 0 {
self.tableView.backgroundView = .none;
return contacts.count
} else {
Helper.EmptyMessage(message: ConstantMap.NO_CONTACT_FOUND, viewController: self)
return 0
}
}
}
Клас помічника з функцією:
/* Description: This function generate alert dialog for empty message by passing message and
associated viewcontroller for that function
- Parameters:
- message: message that require for empty alert message
- viewController: selected viewcontroller at that time
*/
static func EmptyMessage(message:String, viewController:UITableViewController) {
let messageLabel = UILabel(frame: CGRect(x: 0, y: 0, width: viewController.view.bounds.size.width, height: viewController.view.bounds.size.height))
messageLabel.text = message
let bubbleColor = UIColor(red: CGFloat(57)/255, green: CGFloat(81)/255, blue: CGFloat(104)/255, alpha :1)
messageLabel.textColor = bubbleColor
messageLabel.numberOfLines = 0;
messageLabel.textAlignment = .center;
messageLabel.font = UIFont(name: "TrebuchetMS", size: 18)
messageLabel.sizeToFit()
viewController.tableView.backgroundView = messageLabel;
viewController.tableView.separatorStyle = .none;
}
Можливо, це не найкраще рішення, але я це зробив, просто поставивши мітку в нижній частині моєї таблиці, і якщо рядки = 0, то я присвоюю їй якийсь текст. Досить просто та досягає того, що ви намагаєтеся зробити, за допомогою кількох рядків коду.
У мене в розділі два розділи (робочі місця та школи)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (jobs.count == 0 && schools.count == 0) {
emptyLbl.text = "No jobs or schools"
} else {
emptyLbl.text = ""
}
Найпростіший і швидкий спосіб зробити це - перетягнути мітку на бічну панель під tableView. Створіть розетку для мітки та tableView та додайте оператор if, щоб приховати та показати мітку та таблицю за потребою. Крім того, ви можете додати tableView.tableFooterView = UIView (фрейм: CGRect.zero) для цього viewDidLoad (), щоб дати порожній таблиці уявлення про те, що він прихований, якщо подання таблиці та фону мають однаковий колір.
Я вніс кілька змін, щоб нам не потрібно перевіряти кількість рахунків вручну, також я додав обмеження для мітки, щоб нічого не пішло не так, незалежно від того, наскільки велике повідомлення, як показано нижче:
extension UITableView {
fileprivate func configureLabelLayout(_ messageLabel: UILabel) {
messageLabel.translatesAutoresizingMaskIntoConstraints = false
let labelTop: CGFloat = CGFloat(UIDevice.current.userInterfaceIdiom == .pad ? 25:15)
messageLabel.topAnchor.constraint(equalTo: backgroundView?.topAnchor ?? NSLayoutAnchor(), constant: labelTop).isActive = true
messageLabel.widthAnchor.constraint(equalTo: backgroundView?.widthAnchor ?? NSLayoutAnchor(), constant: -20).isActive = true
messageLabel.centerXAnchor.constraint(equalTo: backgroundView?.centerXAnchor ?? NSLayoutAnchor(), constant: 0).isActive = true
}
fileprivate func configureLabel(_ message: String) {
let messageLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.bounds.size.height))
messageLabel.textColor = .black
messageLabel.numberOfLines = 0
messageLabel.textAlignment = .center
let fontSize = CGFloat(UIDevice.current.userInterfaceIdiom == .pad ? 25:15)
let font: UIFont = UIFont(name: "MyriadPro-Regular", size: fontSize) ?? UIFont()
messageLabel.font = font
messageLabel.text = message
self.backgroundView = UIView()
self.backgroundView?.addSubview(messageLabel)
configureLabelLayout(messageLabel)
self.separatorStyle = .none
}
func setEmptyMessage(_ message: String, _ isEmpty: Bool) {
if isEmpty { // instead of making the check in every TableView DataSource in the project
configureLabel(message)
}
else {
restore()
}
}
func restore() {
self.backgroundView = nil
self.separatorStyle = .singleLine
}
}
Використання
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let message: String = "The list is empty."
ticketsTableView.setEmptyMessage(message, tickets.isEmpty)
return self.tickets.count
}
Або ж ви можете використовувати трохи настроювану легку бібліотеку