处理空的UITableView。打印友好的信息

时间:2013-04-01 15:53:00

标签: iphone ios uitableview uiview

我有一个UITableView,在某些情况下,空是合法的。所以不要显示 应用程序的背景图片,我更喜欢在屏幕上打印一条友好的消息,例如:

  

此列表现在为空

最简单的方法是什么?

22 个答案:

答案 0 :(得分:150)

UITableView的backgroundView属性是你的朋友。

viewDidLoadreloadData的任何地方,您应该确定您的表是否为空,并使用包含UILabel的UIView更新UITableView的backgroundView属性,或者将其设置为nil。就是这样。

当然可以让UITableView的数据源执行双重任务并返回一个特殊的“list is empty”单元格,它让我感觉像是一个kludge。突然numberOfRowsInSection:(NSInteger)section必须计算未被询问的其他部分的行数,以确保它们也是空的。您还需要创建一个具有空消息的特殊单元格。另外,请不要忘记您可能需要更改单元格的高度以容纳空消息。这一切都是可行的,但看起来像创可贴上的创可贴。

答案 1 :(得分:76)

根据这里的答案,这是我制作的快速课程,您可以在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
    }
}

enter image description here

http://www.appcoda.com/pull-to-refresh-uitableview-empty/

的帮助下

答案 2 :(得分:47)

与Jhonston的答案相同,但我更喜欢它作为扩展名:

{
   data: "date",
   render: function(data, type, full, meta){
      if(type === "display"){
         data = moment.unix(data).format("MMMM DD, YYYY"); 
      }

      return data;
   }
}    

用法:

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

答案 3 :(得分:14)

我推荐以下库:DZNEmptyDataSet

在项目中添加它的最简单方法是将它与Cocaopods一起使用,如:import DZNEmptyDataSet

在TableViewController中添加以下import语句(Swift):

DNZEmptyDataSetSource

然后确保您的类符合DZNEmptyDataSetDelegateclass 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)
}

现在你需要做的就是显示空状态:

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

这些方法不是强制性的,也可以只显示没有按钮等的空状态。

适用于Swift 4

self.authListener = FIRAuth.auth()?.addAuthStateDidChangeListener { auth, user in
            if let theUser = user {
                // User is signed in.
                print("LOGGED IN!!!!  :::: \(theUser)")
                self.dismissViewControllerAnimated(true, completion: nil)
            } else {
                // No user is signed in.
                print("Need to login first.")
            }
        }

答案 4 :(得分:12)

执行此操作的一种方法是在行数为零时修改数据源以返回1,并在{{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实例进行设置。

答案 5 :(得分:9)

我一直在使用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;
}

答案 6 :(得分:6)

因此,为了更安全的解决方案:

class Object(QObject):

    def __init__(self, parent=None):
        super(Object, self).__init__(parent)
        self.field = []


class Object2(Object):

    def __init__(self):
        super(Object, self).__init__()
        self.field.append(1)

if __name__ == '__main__':
    o = Object2()

以及AttributeError: 'Object2' object has no attribute 'field'

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

答案 7 :(得分:5)

我只能建议在单元格之后将一个UITextView拖放到TableView中。建立与ViewController的连接并在适当时隐藏/显示它(例如,每当表重新加载时)。

enter image description here

答案 8 :(得分:4)

使用backgroundView很好,但它不像Mail.app那样滚动得很好。

我做了类似xtravar所做的事情。

我在tableViewController的视图层次结构外添加了一个视图。 hierarchy

然后我在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

答案 9 :(得分:4)

根据Apple使用容器视图控制器是正确的方法。

我将所有空状态视图放在一个单独的故事板中。每个都在它自己的UIViewController子类下。我直接在他们的根视图下添加内容。如果需要任何动作/按钮,您现在已经有一个控制器来处理它 然后,只需从该Storyboard实例化所需的视图控制器,将其添加为子视图控制器,并将容器视图添加到tableView的层次结构(子视图)。 您的空状态视图也可以滚动,感觉很好,并允许您实现拉动刷新。

Read'将子视图控制器添加到您的内容'以获取有关如何实施的帮助。

只需确保将子视图框设置为 (0, 0, tableView.frame.width, tableView.frame.height)并且事物将集中并正确对齐。

答案 10 :(得分:3)

首先,其他流行方法的问题。

<强> BackgroundView

如果您要使用将其设置为UILabel的简单情况,背景视图并不会很好。

显示消息的单元格,页眉或页脚

这会干扰您的功能代码并引入奇怪的边缘情况。如果您想要完美地集中信息,那就会增加另一种复杂程度。

滚动自己的表格视图控制器

您将失去内置功能,例如refreshControl,并重新发明轮子。坚持使用UITableViewController以获得最佳的可维护性结果。

将UITableViewController添加为子视图控制器

我有一种感觉,你最终会遇到iOS 7+中的contentInset问题 - 加上为什么会让事情复杂化?

我的解决方案

我提出的最佳解决方案(并且,授予,这不是理想的)是制作一个可以位于滚动视图顶部并采取相应行动的特殊视图。在iOS 7中,这显然会因contentInset疯狂而变得复杂,但它是可行的。

你需要注意的事项:

  • 表分隔符在reloadData期间的某个时刻被带到前面 - 你需要防范
  • contentInset / contentOffset - 在特殊视图中观察这些键
  • 键盘 - 如果您不想让键盘挡住,那就是另一个计算
  • 自动布局 - 您无法依靠框架更改来定位视图

一旦你在一个UIView子类中找到了这个,就可以将它用于所有事情 - 加载微调器,禁用视图,显示错误信息等等。

答案 11 :(得分:2)

这是最好和最简单的解决方案。

    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;

答案 12 :(得分:2)

您可以将其添加到您的基类。

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

答案 13 :(得分: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!")
}

记住:     不要忘记删除消息标签,以防刷新后出现数据。

答案 14 :(得分:1)

在storyboard中选择tableviewController场景

enter image description here

拖放UIView 添加带有消息的标签(例如:无数据)

enter image description here

在TableViewController上创建UIView的插座(比如说,例如yournoDataView)。

并在viewDidLoad

self.tableView.backgroundView = yourNoDataView

答案 15 :(得分:1)

多个数据集和部分有一个特定的用例,您需要为每个部分保留空白状态。

您可以使用在此问题的多个答案中提到的建议-提供自定义的空状态单元格。

我将尝试以编程的方式向您详细介绍所有步骤,希望对您有所帮助。这是我们可以期待的结果:

enter image description here

为简单起见,我们将使用2个数据集(2个部分),它们将是静态的。

我还将假设您的其余tableView逻辑可正确处理数据集,tabvleView单元格和节。

Swift 5 ,让我们这样做:

1。创建一个自定义的空状态UITableViewCell类:

class EmptyTableViewCell: UITableViewCell {

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    let label: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "Empty State Message"
        label.font = .systemFont(ofSize: 16)
        label.textColor = .gray
        label.textAlignment = .left
        label.numberOfLines = 1
        return label
    }()

    private func setupView(){
        contentView.addSubviews(label)
        let layoutGuide = contentView.layoutMarginsGuide
        NSLayoutConstraint.activate([
            label.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor),
            label.topAnchor.constraint(equalTo: layoutGuide.topAnchor),
            label.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor),
            label.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor),
            label.heightAnchor.constraint(equalToConstant: 50)
        ])
    }
}

2。将以下内容添加到您的UITableViewController类中以注册您的空单元格:

class TableViewController: UITableViewController {
    ...
    let emptyCellReuseIdentifier = "emptyCellReuseIdentifier"
    ...
    override func viewDidLoad(){
        ...
        tableView.register(EmptyTableViewCell.self, forCellReuseIdentifier: emptyCellReuseIdentifier)
        ...
    }
}

3。现在,让我们重点介绍上面提到的一些假设:

class TableViewController: UITableViewController {
    // 2 Data Sets
    var firstDataSet: [String] = []
    var secondDataSet: [String] = []

    // Sections array
    let sections: [SectionHeader] = [
        .init(id: 0, title: "First Section"),
        .init(id: 1, title: "Second Section")
    ]
    ...
    // MARK: - Table view data source
    override func numberOfSections(in tableView: UITableView) -> Int {
        sections.count
    }
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sections[section].title
    }
        ...
    }

struct SectionHeader {
    let id: Int
    let title: String
}

4。现在,让我们向数据源添加一些自定义逻辑,以处理各节中的空行。 如果数据集为空,我们将在此处返回1行:

class TableViewController: UITableViewController {
    ...
    // MARK: - Table view data source
    ...
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        switch section{
        case 0:
            let numberOfRows = firstDataSet.isEmpty ? 1 : firstDataSet.count
            return numberOfRows          
        case 1:
            let numberOfRows = secondDataSet.isEmpty ? 1 : secondDataSet.count
            return numberOfRows   
        default:
            return 0
        }
    }
    ...
}

5。最后,最重要的“ cellForRowAt indexPath”:

class TableViewController: UITableViewController {
    ...
    // MARK: - Table view data source
    ...
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        // Handle Empty Rows State
        switch indexPath.section {
        case 0:
            if firstDataSet.isEmpty {
                if let cell = tableView.dequeueReusableCell(withIdentifier: emptyCellReuseIdentifier) as? EmptyTableViewCell {
                    cell.label.text = "First Data Set Is Empty"
                    return cell
                }
            }
        case 1:
            if secondDataSet.isEmpty {
                if let cell = tableView.dequeueReusableCell(withIdentifier: emptyCellReuseIdentifier) as? EmptyTableViewCell {
                    cell.label.text = "Second Data Set Is Empty"
                    return cell
                }
            }
        default:
            break
        }
        
        // Handle Existing Data Sets
        if let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as? TableViewCell {
            switch indexPath.section {
            case 0:
                ...
            case 1:
                ...
            default:
                break
            }
            return cell
        }

        return UITableViewCell()
    }
    ...
}

答案 16 :(得分: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 = ""
    }

答案 17 :(得分:0)

最简单,最快捷的方法是将标签拖到tableView下的侧面板上。为标签和tableView创建出口,并添加if语句以根据需要隐藏和显示标签和表格。或者,您可以将tableView.tableFooterView = UIView(frame:CGRect.zero)添加到您的viewDidLoad()中,以使空表感知到如果表和背景视图具有相同的颜色,则该表是隐藏的。

答案 18 :(得分:0)

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

答案 19 :(得分: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
    }

答案 20 :(得分:0)

或者,您也可以使用可自定义的轻量级库

SwiftEmptyState

答案 21 :(得分:0)

Swift版本,但更好更简单的形式。 ** 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;
        }