如果没有“表视图”结果,则在屏幕上显示“无结果”


114

我有一个tableview,有时可能没有任何结果要列出,因此如果没有结果(标签或一个表视图单元格?),我想说一句“无结果”

有最简单的方法吗?

我会尝试label在结果tableview之后隐藏一个,然后根据结果隐藏两者之一,但是由于我使用的是a TableViewController而不是普通的,因此ViewController我不确定这有多聪明或可行。

我也使用Parse和子类化为PFQueryTableViewController

@interface TableViewController : PFQueryTableViewController

我可以提供所需的任何其他详细信息,请告诉我!

TableViewController 故事板中的场景:

在此处输入图片说明

编辑: Per Midhun MP,这是我正在使用的代码

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    NSInteger numOfSections = 0;
    if ([self.stringArray count] > 0)
    {
        self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
        numOfSections                 = 1;
        //yourTableView.backgroundView   = nil;
        self.tableView.backgroundView = nil;
    }
    else
    {
        UILabel *noDataLabel         = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, self.tableView.bounds.size.height)];
        noDataLabel.text             = @"No data available";
        noDataLabel.textColor        = [UIColor blackColor];
        noDataLabel.textAlignment    = NSTextAlignmentCenter;
        //yourTableView.backgroundView = noDataLabel;
        //yourTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        self.tableView.backgroundView = noDataLabel;
        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    }

    return numOfSections;
}

这是我得到的视图,它仍然具有分隔线。我感觉这是一个很小的变化,但是我不确定为什么显示分隔线?

在此处输入图片说明


我认为诀窍是在tableview上设置空的footerView来摆脱行。
本辛克莱

@Andy那是什么意思?
SRMR 2015年

不要使用添加到此问题的解决方案。表格视图数据源方法决不能做超出其应做的事情。numberOfSections应该返回一个计数,就是这样。相同numberOfRowsInSection。这些可以在任何时间多次调用。除返回计数外,切勿更新视图或更新数据或执行任何操作。更新视图的逻辑决不能使用这些方法。
rmaddy

Answers:


206

通过使用的backgroundView属性,您可以轻松实现这一目标UITableView

目标C:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    NSInteger numOfSections = 0;
    if (youHaveData)
    {
        yourTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
        numOfSections                = 1;
        yourTableView.backgroundView = nil;
    }
    else
    {   
        UILabel *noDataLabel         = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, yourTableView.bounds.size.width, yourTableView.bounds.size.height)];
        noDataLabel.text             = @"No data available";
        noDataLabel.textColor        = [UIColor blackColor];
        noDataLabel.textAlignment    = NSTextAlignmentCenter;
        yourTableView.backgroundView = noDataLabel;
        yourTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    }

    return numOfSections;
}

迅速:

func numberOfSections(in tableView: UITableView) -> Int
{
    var numOfSections: Int = 0
    if youHaveData
    {
        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 data available"
        noDataLabel.textColor     = UIColor.black
        noDataLabel.textAlignment = .center
        tableView.backgroundView  = noDataLabel
        tableView.separatorStyle  = .none
    }
    return numOfSections
}

参考UITableView类参考

backgroundView 属性

表格视图的背景视图。

宣言

迅速

var backgroundView: UIView?

目标C

@property(nonatomic, readwrite, retain) UIView *backgroundView

讨论区

表格视图的背景视图会自动调整大小以匹配表格视图的大小。该视图作为表格视图的子视图放置在所有单元格,页眉视图和页脚视图的后面。

您必须将此属性设置为nil才能设置表格视图的背景色。


感谢你的回答!这是否意味着我需要一个tableView插座才能使用yourTableView.backgroundView?我正在使用一个,TableViewController所以我现在没有插座,这就是为什么我想知道。
SRMR

1
UITableViewController已经有一个名为的属性,tableView因此您无需创建一个属性
Cihan Tek

使用self.tableView
SRMR

1
更正。经过进一步的测试,我实际上不得不使我提到的那一行返回相同的值。numOfSections =1。如果我将其设置为零,并且表视图为空,则它可以工作,但是当我创建一个单元格然后将其删除而不是删除并显示消息时,它将崩溃并显示以下错误。***由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'UITableView内部错误:无法生成旧节计数为1且新节计数为0的新节映射。我不知道为什么返回相同的值行得通,但是它确实行得通,并且应该如何行得通。
ChrisOSX

2
不要使用此解决方案。表格视图数据源方法决不能做超出其应做的事情。numberOfSections应该返回一个计数,就是这样。相同numberOfRowsInSection。这些可以在任何时间多次调用。除返回计数外,切勿更新视图或更新数据或执行任何操作。更新视图的逻辑决不能使用这些方法。
rmaddy

107

对于Xcode 8.3.2-Swift 3.1

这是一种鲜为人知但非常简单的方法,可以实现将“无项目”视图添加到可追溯到Xcode 7的空表视图中。我将由您来控制添加/删除该逻辑的逻辑。视图到表的背景视图,但这是Xcode(8.3.2)故事板的流程:

  1. 在具有您的表格视图的情节提要中选择场景。
  2. 将一个空的UIView拖到该场景的“场景扩展坞”

在此处输入图片说明

  1. 将UILabel和所有约束添加到新视图,然后为该视图创建IBOutlet

在此处输入图片说明

  1. 将该视图分配给tableView.backgroundView

在此处输入图片说明

  1. 看魔术!

在此处输入图片说明

最终,这可以在您想要向视图控制器中添加一个简单视图(不一定要立即显示,但又不想手工编码)时起作用。


1
该技术适用于您需要简单查看的任何内容。我也将其用于自定义表格节标题。确实,您可以将其用于需要查看的任何内容。只需通过IBOutlet引用,然后将其添加为子视图即可。
Paul Bonneville

正如@gmogames所说的,在做IOS两年之后,这是第一次了解tableView背景!。谢谢男人
阿里·阿迪尔

1
谢谢你 只是把它放在那里,我不得不使用tableView.separatorStyle = .none并调整默认UIView的大小以查看backgroundView。我使用的Xcode 9.4雨燕4
哈马德塔里克

您如何放置自定义视图?
Nol4635

1
@ Nol4635对于tableview背景,您只需将创建为IBOutlet的视图分配给tableview的背景,或者,如果您只想将该视图添加到其他视图,则可以将其添加为子视图。您必须设置框架值,但这与其他任何视图一样。
保罗·邦纳维尔

30

以上代码的Swift版本:

func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    var numOfSection: NSInteger = 0

    if CCompanyLogoImage.count > 0 {

        self.tableView.backgroundView = nil
        numOfSection = 1


    } else {

        var noDataLabel: UILabel = UILabel(frame: CGRectMake(0, 0, self.tableView.bounds.size.width, self.tableView.bounds.size.height))
        noDataLabel.text = "No Data Available"
        noDataLabel.textColor = UIColor(red: 22.0/255.0, green: 106.0/255.0, blue: 176.0/255.0, alpha: 1.0)
        noDataLabel.textAlignment = NSTextAlignment.Center
        self.tableView.backgroundView = noDataLabel

    }
    return numOfSection
}

但是,如果您要从JSON加载信息,则需要检查JSON是否为空,因此,如果放置这样的代码,它最初显示为“ No data”,然后消息消失。因为在表重新加载数据后,消息会隐藏。因此,您可以将此代码放在将JSON数据加载到数组的位置。所以:

func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    return 1
}

func extract_json(data:NSData) {


    var error: NSError?

    let jsonData: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers , error: &error)
    if (error == nil) {
        if let jobs_list = jsonData as? NSArray
        {
            if jobs_list.count == 0 {

                var noDataLabel: UILabel = UILabel(frame: CGRectMake(0, 0, self.tableView.bounds.size.width, self.tableView.bounds.size.height))
                noDataLabel.text = "No Jobs Available"
                noDataLabel.textColor = UIColor(red: 22.0/255.0, green: 106.0/255.0, blue: 176.0/255.0, alpha: 1.0)
                noDataLabel.textAlignment = NSTextAlignment.Center
                self.tableView.backgroundView = noDataLabel

            }

            for (var i = 0; i < jobs_list.count ; i++ )
            {
                if let jobs_obj = jobs_list[i] as? NSDictionary
                {
                    if let vacancy_title = jobs_obj["VacancyTitle"] as? String
                    {
                        CJobTitle.append(vacancy_title)

                        if let vacancy_job_type = jobs_obj["VacancyJobType"] as? String
                        {
                            CJobType.append(vacancy_job_type)

                            if let company_name = jobs_obj["EmployerCompanyName"] as? String
                            {
                                CCompany.append(company_name)

                                    if let company_logo_url = jobs_obj["EmployerCompanyLogo"] as? String
                                    {
                                        //CCompanyLogo.append("http://google.com" + company_logo_url)

                                        let url = NSURL(string: "http://google.com" + company_logo_url )
                                        let data = NSData(contentsOfURL:url!)
                                        if data != nil {
                                            CCompanyLogoImage.append(UIImage(data: data!)!)
                                        }

                                        if let vacancy_id = jobs_obj["VacancyID"] as? String
                                        {
                                            CVacancyId.append(vacancy_id)

                                        }

                                    }

                            }

                        }
                    }
                }
            }
        }
    }
    do_table_refresh();


}

func do_table_refresh() {

    dispatch_async(dispatch_get_main_queue(), {
        self.tableView.reloadData()
        return
    })
}

当行中没有数据时,这对于显示标签非常有用。但是,什么时候处理数据self.tableView.reloadData()并被调用的最佳方法是什么?我发现它正在添加我的新行,但noDataLabel仍显示在它们的下面。
tylerSF '16

1
如果您的数组中有项目,只需设置self.tableView.backgroundView = nil
Chathuranga Silva

如果Jobs_list.count == 0 {//添加上面给定的代码} else {self.tableView.backgroundView = nil}
Chathuranga Silva

完善。self.tableView.backgroundView = nil在我的if语句之前添加return jobs_list.count 效果很好。谢谢
tylerSF '16

不要在此答案中使用第一个解决方案。表格视图数据源方法决不能做超出其应做的事情。numberOfSections应该返回一个计数,就是这样。相同numberOfRowsInSection。这些可以在任何时间多次调用。除返回计数外,切勿更新视图或更新数据或执行任何操作。更新视图的逻辑决不能使用这些方法。
rmaddy

6

您可以尝试使用此控件。它非常整洁。DZNEmptyDataSet

或者如果我是你,我会做的就是

  • 检查数据数组是否为空
  • 如果为空,则向其中添加一个名为@“ No Data”的对象
  • 在cell.textLabel.text中显示该字符串

十分简单


5

Swift 3(更新):

override func numberOfSections(in tableView: UITableView) -> Int {
    if myArray.count > 0 {
        self.tableView.backgroundView = nil
        self.tableView.separatorStyle = .singleLine
        return 1
    }

    let rect = CGRect(x: 0,
                      y: 0,
                      width: self.tableView.bounds.size.width,
                      height: self.tableView.bounds.size.height)
    let noDataLabel: UILabel = UILabel(frame: rect)

    noDataLabel.text = "Custom message."
    noDataLabel.textColor = UIColor.white
    noDataLabel.textAlignment = NSTextAlignment.center
    self.tableView.backgroundView = noDataLabel
    self.tableView.separatorStyle = .none

    return 0
}

不要使用此解决方案。表格视图数据源方法决不能做超出其应做的事情。numberOfSections应该返回一个计数,就是这样。相同numberOfRowsInSection。这些可以在任何时间多次调用。除返回计数外,切勿更新视图或更新数据或执行任何操作。更新视图的逻辑决不能使用这些方法。
rmaddy

我同意。该解决方案可以改进,但也可以使用。
Teodor Ciuraru

您如何同意不应该使用此解决方案,而是声明可以使用该解决方案?这是一个矛盾。
rmaddy

我同意可以改进此解决方案,但是在当前状态下也可以使用。
Teodor Ciuraru

5

迅捷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;
        }

不要使用此解决方案。表格视图数据源方法决不能做超出其应做的事情。numberOfSections应该返回一个计数,就是这样。相同numberOfRowsInSection。这些可以在任何时间多次调用。除返回计数外,切勿更新视图或更新数据或执行任何操作。更新视图的逻辑决不能使用这些方法。
rmaddy

3

我认为解决问题的最优雅方法是从a切换UITableViewControllerUIViewController包含a的a UITableView。这样,您可以将所需的任何UIView内容添加为主视图的子视图。

我不建议您使用UITableViewCell来执行此操作,您将来可能需要添加其他内容,而这些内容很快就会变得丑陋。

您也可以这样做,但这也不是最好的解决方案。

UIWindow* window = [[UIApplication sharedApplication] keyWindow];
[window addSubview: OverlayView];

感谢周围的颜色是最优雅的实现方式,始终是考虑它的好方法。我可能会尝试将情节提要更改为使用UIViewController包含UITableView
SRMR

1
这是最适合未来的方法。我从未使用过UITableViewController自己,因为使用它实际上并不比用另一种方法简单得多,但是它限制了您将来改变事物的能力。
Cihan Tek

如果您有半透明的条形,则这不是面向未来的。我强烈建议您反对。至少要制作一个包含UITableViewController并适当调整内容的UIViewController。
xtravar

3

在您的numberOfSectionsInTableView方法中使用此代码:-

if ([array count]==0
{

    UILabel *fromLabel = [[UILabel alloc]initWithFrame:CGRectMake(50, self.view.frame.size.height/2, 300, 60)];                                                                                        
    fromLabel.text =@"No Result";
    fromLabel.baselineAdjustment = UIBaselineAdjustmentAlignBaselines;
    fromLabel.backgroundColor = [UIColor clearColor];
    fromLabel.textColor = [UIColor lightGrayColor];
    fromLabel.textAlignment = NSTextAlignmentLeft;
    [fromLabel setFont:[UIFont fontWithName:Embrima size:30.0f]];
    [self.view addSubview:fromLabel];
    [self.tblView setHidden:YES];
}

1
不要使用此解决方案。表格视图数据源方法决不能做超出其应做的事情。numberOfSections应该返回一个计数,就是这样。相同numberOfRowsInSection。这些可以在任何时间多次调用。除返回计数外,切勿更新视图或更新数据或执行任何操作。更新视图的逻辑决不能使用这些方法。
rmaddy

2

SWIFT 3

        let noDataLabel: UILabel     = UILabel(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: tableView.bounds.size.height))
        noDataLabel.text             = "No data available"
        noDataLabel.textColor        = UIColor.white
        noDataLabel.font             = UIFont(name: "Open Sans", size: 15)
        noDataLabel.textAlignment    = .center
        tableView.backgroundView = noDataLabel
        tableView.separatorStyle = .none

2

如果您不使用tableview页脚,并且不希望tableview用空的默认表单元格填充屏幕,那么我建议您将tableview页脚设置为空的UIView。我不知道在obj-c或Swift中执行此操作的正确语法,但是在Xamarin.iOS中我会这样做:

public class ViewController : UIViewController
{
    UITableView _table;

    public ViewController (IntPtr handle) : base (handle)
    {
    }

    public override void ViewWillAppear(bool animated) {
        // Initialize table

        _table.TableFooterView = new UIView();
    }
}

上面的代码将导致没有空单元格的表视图


2

这是对我有用的解决方案。

  1. 将以下代码添加到新文件中。

  2. 从情节提要或.xib将表类更改为自定义类“ MyTableView”

(这仅适用于第一部分。如果要自定义更多内容,请对其他部分相应地在MyTableView reloadData()函数中进行更改)

public class MyTableView: UITableView {

    override public func reloadData() {
        super.reloadData()

        if self.numberOfRows(inSection: 0) == 0 {
            if self.viewWithTag(1111) == nil {
                let noDataLabel = UILabel()
                noDataLabel.textAlignment = .center
                noDataLabel.text = "No Data Available"
                noDataLabel.tag = 1111
                noDataLabel.center = self.center
                self.backgroundView = noDataLabel
            }

        } else {
            if self.viewWithTag(1111) != nil {
                self.backgroundView = nil
            }
        }
    }
}

这是一个好方法。我添加了一些增强功能,使其更全面。1.缓存tableview的分隔符样式,并在进行空/非空状态转换时将其还原,以使此子类适用于需要使用不同分隔符样式的用例。2.添加@IBInspectable var emptyStateText: String?并标记该类,因为@IBDesignable这样您将能够为情节提要或xib中的不同场景更改不同的空状态文本。请享用!:)
Egist Li

1

如果tableview没有结果,我将显示一个叠加视图,该视图具有所需的外观和消息。您可以在ViewDidAppear中执行此操作,因此在显示/不显示视图之前可以得到结果。


1

如果您想在没有任何代码的情况下执行此操作,请尝试此操作!

单击您的tableView。

tableView截图

将样式从“普通”更改为“分组”。

表格视图属性屏幕截图2

现在,当您使用....

tableView.backgroundView =插入标签或视图

它不会显示分隔符!


1

将此代码添加到一个文件中,然后将您的集合类型更改为CustomCollectionView

import Foundation

class CustomCollectionView: UICollectionView {

  var emptyModel = EmptyMessageModel()
  var emptyView: EmptyMessageView?
  var showEmptyView: Bool = true

  override func reloadData() {
    super.reloadData()

    emptyView?.removeFromSuperview()
    self.backgroundView = nil

    if !showEmptyView {
      return
    }

    if numberOfSections < 1 {
      let rect = CGRect(x: 0,
                        y: 0,
                        width: self.bounds.size.width,
                        height: self.bounds.size.height)

      emptyView = EmptyMessageView()
      emptyView?.frame = rect
      if let emptyView = emptyView {
        //                self.addSubview(emptyView)
        self.backgroundView = emptyView
      }
      emptyView?.setView(with: emptyModel)

    } else {
      emptyView?.removeFromSuperview()
      self.backgroundView = nil
    }
  }
}

class EmptyMessageView: UIView {

  @IBOutlet weak var messageLabel: UILabel!
  @IBOutlet weak var imageView: UIImageView!

  var view: UIView!

  override init(frame: CGRect) {
    super.init(frame: frame)
    xibSetup()
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    xibSetup()
  }

  func xibSetup() {
    view = loadViewFromNib()

    view.frame = bounds

    view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    addSubview(view)
  }

  func loadViewFromNib() -> UIView {

    let bundle = Bundle(for: type(of: self))
    let nib = UINib(nibName: "EmptyMessageView", bundle: bundle)
    let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView

    return view
  }

  func setView(with model: EmptyMessageModel) {
    messageLabel.text = model.message ?? ""
    imageView.image = model.image ?? #imageLiteral(resourceName: "no_notification")
  }
}

///////////
class EmptyMessageModel {
  var message: String?
  var image: UIImage?

  init(message: String = "No data available", image: UIImage = #imageLiteral(resourceName: "no_notification")) {
    self.message = message
    self.image = image
  }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.