Обробка порожнього UITableView. Роздрукуйте дружнє повідомлення


124

У мене є UITableView, що в деяких випадках законно бути порожнім. Тому замість показу фонового зображення програми я вважаю за краще надрукувати дружнє повідомлення на екрані, наприклад:

Цей список тепер порожній

Який найпростіший спосіб це зробити?


10
Перевірте цей проект: github.com/dzenbot/DZNEmptyDataSet
oleynikd

@oleynikd Дякую !!!!!
Люда

Відповіді:


173

Властивість backgroundView UITableView - ваш друг.

В viewDidLoad будь-якому місці, де reloadDataвам слід визначити, чи є ваша таблиця порожнім чи ні, і оновіть властивість backgroundView UITableView за допомогою UIView, що містить UILabel, або просто встановіть його на нуль. Це воно.

Звичайно, можна змусити джерело даних UITableView виконувати подвійний обов'язок і повертати спеціальну клітинку "список порожній", це сприймає мене як хитрощі. Раптом numberOfRowsInSection:(NSInteger)sectionдоводиться обчислювати кількість рядків інших розділів, про які не запитували, щоб переконатися, що вони теж порожні. Вам також потрібно зробити спеціальну комірку, яка містить порожнє повідомлення. Також не забувайте, що вам потрібно, ймовірно, змінити висоту своєї комірки, щоб вмістити порожнє повідомлення. Це все можливо, але здається, що це допомога на вершині верхньої групи.


12
Я думаю, що backgroundView - найкраще рішення. Дякую!
Ферран Мейлінч

1
Одним недоліком є ​​те, що якщо вигляд таблиці знижується, повідомлення залишається на своєму місці. Я б хотів, щоб це було в додатку магазину додатків під час оновлень. Тут порожнє повідомлення йде з поведінкою прокрутки ...
тестування

@ Протестуючи, очевидно, якщо для прокрутки вам потрібні порожні повідомлення, ви не можете використовувати фоновий вигляд, оскільки це не є частиною ієрархії прокрутки. Можливо, ви хочете використовувати користувальницький розділ і UITableViewCell для порожнього стану.
LightningStryk

Змінити backgroundViewприховану власність - це шлях. З DZNEmptyDataSet, ми повинні використовувати йогоemptyDataSetSource
onmyway133

Якщо ви хочете додати кнопки, ви повинні зробити: tableView.backgroundView!.userInteraction = trueпісля рядка, який ви встановили tableView.backgroundView = constructMyViewWithButtons(), або як би ви його встановили.
kbpontius

90

Те саме, що відповідь Джонстона, але я вважав за краще це продовження:

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
}

Дякую за пропозицію
ssowri1

1
Розширення краще! Дякую.
Огулькан Орхан

Любіть розширення :)
Алікс

1
Якщо у вас є розділи, вам потрібно буде перенести цю логіку на func numberOfSections(in tableView: UITableView) -> Intметод
ремесло

87

Виходячи з відповідей тут, ось короткий клас, який я склав, і який ви можете використовувати у своєму 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/


хотіли б також додати до нього зображення. Але чудове швидке рішення.
AnBisw

10
використовуйте розширення замість класу (не передайте контролер перегляду)
Cesare

Я не зміг змусити код, який працює вище для мене, але мені вдалося змусити код у цій відповіді (перший) працювати, якщо у інших є та сама проблема. Також я думаю, що 2-я відповідь також спрацює (використовуючи док-станцію) - stackoverflow.com/questions/28532926/…
Рене Олсон,

viewController.tableView.separatorStyle = .noneне потрібно.
Дмитро

17

Я рекомендую таку бібліотеку: 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)
}

У мене виникають проблеми з тим, що DZEmptyDataSet не є вертикально вирівняним належним чином. Хтось мав таке саме питання?
amariduran

12

Одним із способів цього буде модифікація джерела даних, щоб повернутись, 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що було налаштовано відповідним повідомленням.


5
У мене виникли проблеми з таблицями, у яких рядки видалено, deleteRowsAtIndexPaths:withRowAnimation:оскільки число, повернене з numberOfRowsInSectionпотреб, відповідає результату $ numRows - $ rowsDeleted.
Animal451

4
Я дуже настійно рекомендую проти цього. Він загадує ваш код крайовими коробками.
xtravar

2
@xtravar Замість того, щоб зволікати, подумайте над публікацією власної відповіді.
dasblinkenlight

1
Я пройшов цей шлях, і це призводить до власного масиву проблем. На мій досвід, майже завжди краще розширювати API Apple, ніж намагатися замінити їх.
xtravar

1
Це рішення не працюватиме з NSFetchedResultsController. Я замість цього спробую спробувати підхід backgroundView.
Сем

10

Я використовую для цього повідомлення 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;
}

2
Гарний трюк і здається мені досить чистим. Ось один лайнер:return tableView.numberOfRowsInSection(section) == 0 ? "This list is now empty" : nil
TruMan1

8

Тож для більш безпечного рішення:

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

7

Я можу лише порекомендувати перетягувати UITextView всередину TableView після комірок. Встановіть підключення до ViewController і при необхідності прихойте / відображіть його (наприклад, коли таблиця перезавантажується).

введіть тут опис зображення


Це найпростіший спосіб)!
moonvader

Така болісна головний біль яблучним шляхом; дякую за цю ідею
Eenvincible

5

Використання 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та переконайтесь, що він змінює розмір .
Ганнеле

4

Використання контролера перегляду контейнерів - це правильний спосіб зробити це відповідно до Apple .

Я розміщую всі свої порожні погляди стану в окрему дошку розкадрувань. Кожен під власним підкласом UIViewController. Я додаю вміст безпосередньо під їх кореневим поданням. Якщо потрібні будь-які дії / кнопки, тепер у вас вже є контролер, який обробляє це.
Тоді справа лише в тому, щоб створити потрібний контролер подання з цієї дошки розкадри, додати його як дочірній контролер подання та додати перегляд контейнера до ієрархії tableView (підподання). Ваш порожній вигляд стану також буде прокручуватися, що почуває себе добре і дозволить вам реалізувати функцію "тягнути" для оновлення.

Прочитайте розділ "Додавання контролера подання даних до вашого вмісту", щоб дізнатися, як реалізувати.

Просто переконайтеся, що ви встановили дочірню рамку перегляду як, (0, 0, tableView.frame.width, tableView.frame.height)і речі будуть зосереджені та вирівняні належним чином.


3

По-перше, проблеми з іншими популярними підходами.

BackgroundView

Перегляд фону не є гарним центром, якщо ви використовували простий випадок встановлення його на UILabel.

Осередки, заголовки або колонтитули для відображення повідомлення

Це втручається у ваш функціональний код та запроваджує дивні випадкові випадки. Якщо ви хочете ідеально центрувати своє повідомлення, це додає іншого рівня складності.

Прокат власного контролера подання таблиці

Ви втрачаєте вбудовану функціональність, таку як refreshControl, і знову винаходите колесо. Дотримуйтесь UITableViewController для отримання найкращих результатів.

Додавання UITableViewController як контролер дочірнього перегляду

У мене є відчуття, що у вас виникнуть проблеми з contentInset в iOS 7+ - плюс чому ускладнюєте речі?

Моє рішення

Найкраще рішення, яке я придумав (і, безумовно, це не ідеально) - зробити спеціальний вигляд, який може сидіти на вершині подання прокрутки і діяти відповідно. Це, очевидно, ускладнюється в iOS 7 з безумством contentInset, але це можливо.

Речі, на які слід стежити:

  • роздільники таблиць виводяться на передню частину під час reloadData - вам потрібно захиститись від цього
  • contentInset / contentOffset - дотримуйтесь цих клавіш на спеціальному вікні
  • клавіатура - якщо ви не хочете, щоб клавіатура заважала, це ще один розрахунок
  • автоматична розкладка - ви не можете залежати від змін кадру, щоб розмістити свій погляд

Після того, як ви це зрозуміли один раз в одному підкласі UIView, ви можете використовувати його для всього - завантаження спінерів, відключення представлень даних, показ повідомлень про помилки тощо.


Чи можете ви детальніше пояснити свою відповідь. Як дізнатися, чи таблиця порожня? Щоб потім "діяти відповідно".
Михайло Озерянський

Ви знаєте, що ваша таблиця порожня, оскільки ви її заповнюєте. Отже, у вашому контролері перегляду ви матимете асинхронний зворотній зв'язок завантаження. У цьому зворотному дзвінку, якщо (itemsToShow.count == 0) {додати свій погляд до подання прокрутки}. Складна частина полягає в тому, що вид зверху ("щит / перегляд повідомлення") розташований так, щоб зайняти весь кадр подання прокрутки, мінус contentInset тощо, щоб повідомлення було по центру вертикально.
xtravar

Як додати перегляд у верхній частині таблиці? self.view - це перегляд таблиці, і якщо я addSubViewйого використовую, він додається до подання таблиці, який завжди створює проблеми з автоматичним компонуванням.
тестування

Представлення, яке ви розміщуєте в межах подання таблиці, не повинно використовувати автоматичне розміщення, а сам перегляд таблиці не використовує автоматичний розклад.
xtravar

1
Ви пропустили один підхід там; Ви можете використовувати UITableViewController і додати його як контролер дочірнього перегляду до звичайного UIViewController
user1169629

3

Це найкраще і просте рішення.

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;

2

Показати Повідомлення для порожнього списку, Збільшити його 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!")
}

Пам'ятайте: не забудьте видалити мітку повідомлення, якщо дані з’являться після оновлення.


1
Я додав би умову if if messages.count! = 0 {показати}
Eddwin Paz

1

Виберіть сценарій tableviewController в сценарій

введіть тут опис зображення

Перетягніть мітку UIView Add із своїм повідомленням (наприклад: Без даних)

введіть тут опис зображення

створити розетку UIView (скажімо, наприклад, yournoDataView) на своєму TableViewController.

і в viewDidLoad

self.tableView.backgroundView = yourNoDataView


1

Використання 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
}

1

Ви можете додати це до свого базового класу.

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

Привіт @ Mudassir-Asghar як виглядає функція hidNoDataMessage?
Саамер

1
Привіт, @Saamer, я щойно оновив відповідь вище. дякую, що вказали на це, сподіваємось, це допоможе :)
Мудассір Асгар

0

Швидка версія, але краща та простіша форма. ** 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

Можливо, це не найкраще рішення, але я це зробив, просто поставивши мітку в нижній частині моєї таблиці, і якщо рядки = 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 = ""
    }

Ви також можете замінити мітку порожнім переглядом зображень, коли кол = 0, якщо хочете ..
Зак

0

Найпростіший і швидкий спосіб зробити це - перетягнути мітку на бічну панель під tableView. Створіть розетку для мітки та tableView та додайте оператор if, щоб приховати та показати мітку та таблицю за потребою. Крім того, ви можете додати tableView.tableFooterView = UIView (фрейм: CGRect.zero) для цього viewDidLoad (), щоб дати порожній таблиці уявлення про те, що він прихований, якщо подання таблиці та фону мають однаковий колір.


(Здається, ця публікація не дає якісної відповіді на питання. Будь ласка, відредагуйте свою відповідь та доповніть її більш детальною інформацією, або просто опублікуйте її як коментар до питання).
sɐunıɔ ןɐ qɐp

0

Я вніс кілька змін, щоб нам не потрібно перевіряти кількість рахунків вручну, також я додав обмеження для мітки, щоб нічого не пішло не так, незалежно від того, наскільки велике повідомлення, як показано нижче:

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
    }

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.