テーブルビューの結果がない場合は、画面に「結果なし」と表示します。


114

私が持っているtableview私は時々 、リストに何も結果があるではないかもしれないところ、それは「何の成果を」言わないまでに何かを入れたい何の結果が存在しない場合(ラベルまたは1つのテーブルビューセルのいずれかが?)。

これを行う最も簡単な方法はありますか?

私がしようとするだろうlabel後ろtableview結果に基づいて、2つの後、皮1、しかし、私が働いているので、TableViewController通常のをしていないViewController私はどのようにスマートわからないか、つまりなんとか。

私はまたParse、としてサブクラスを使用していPFQueryTableViewControllerます:

@interface TableViewController : PFQueryTableViewController

必要な追加の詳細情報を提供できます。通知してください!

TableViewController ストーリーボードのシーン:

ここに画像の説明を入力してください

編集: 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;
}

そして、ここに私が得ているビューがあります、それはまだ区切り線を持っています。これは小さな変更だと感じますが、なぜセパレータ線が表示されるのかわかりません。

ここに画像の説明を入力してください


トリックは、テーブルビューに空のフッタービューを設定して行を取り除くことだったと思います。
Ben Sinclair

@アンディどういう意味ですか?
SRMR 2015年

この質問に追加されたソリューションは使用しないでください。テーブルビューのデータソースメソッドは、想定されている以上のことをしてはなりません。numberOfSectionsカウントを返す必要があり、それだけです。も同じですnumberOfRowsInSection。これらはいつでも何度でも呼び出すことができます。ビューを更新したり、データを更新したり、カウントを返す以外のことを行ったりしないでください。ビューを更新するロジックがこれらのメソッドに含まれていてはなりません。
rmaddy

回答:


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?

Objective-C

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

討論

テーブルビューの背景ビューは、テーブルビューのサイズに合わせて自動的にサイズ変更されます。このビューは、すべてのセル、ヘッダービュー、およびフッタービューの背後にあるテーブルビューのサブビューとして配置されます。

テーブルビューの背景色を設定するには、このプロパティをnilに設定する必要があります。


答えてくれてありがとう!これは私がtableViewできるようにコンセントが必要という意味yourTableView.backgroundViewですか?私はを使用しているTableViewControllerので、今のところコンセントがありません。それが理由です。
SRMR、2015

1
UITableViewControllerという名前のプロパティがすでにあるtableViewため、作成する必要はありません
Cihan Tek

使用して、それを得たself.tableView
SRMR

1
補正。さらにテストを行うと、実際には、前述の行が同じ値を返すようにする必要がありました。numOfSections = 1.ゼロにしてテーブルビューが空の場合は機能しますが、セルを作成してから削除すると、メッセージを削除して表示するのではなく、次のエラーでクラッシュします。***キャッチされない例外 'NSInternalInconsistencyException'によりアプリを終了しています。理由: 'UITableView内部バグ:古いセクションカウントが1で新しいセクションカウントが0の新しいセクションマップを生成できません。同じ値を返すことがなぜ機能するのかはわかりませんが、機能して機能するはずです。
ChrisOSX 2017年

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を介して参照し、カスタムビューが必要な任意の場所にサブビューとして追加します。
ポールボンネビル

@gmogamesが言ったように、2年間IOSを実行した後、これはtableViewのバックグラウンドについて初めて知る!です。おかげで男
アリアディル

1
これをありがとう。ただそこに置くために、私はtableView.separatorStyle = .noneを使用し、backgroundViewを表示するためにデフォルトのUIViewのサイズを変更する必要がありました。私はスウィフト4でのXcode 9.4を使用しています
Hammadタリク

カスタムビューをどのように配置しますか?
Nol4635

1
@ Nol4635テーブルビューのバックグラウンドの場合、作成したビューをIBOutletとしてテーブルビューのバックグラウンドに割り当てるか、ビューを別のビューに追加するだけの場合は、サブビューとして追加できます。フレーム値を設定する必要がありますが、他のビューと同じです。
ポールボンネビル

30

上記のコードのスウィフトバージョン:-

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が空かどうかを確認する必要があります。そのため、このようなコードを配置すると、最初に「データがありません」というメッセージが表示されてから消えます。テーブルをリロードした後、メッセージが非表示になるためです。したがって、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 2016

1
配列に項目がある場合は、self.tableView.backgroundView = nil
Chathuranga Silvaを

if jobs_list.count == 0 {//指定されたコードの上に追加} else {self.tableView.backgroundView = nil}
Chathuranga Silva

完璧。self.tableView.backgroundView = nil前に私のifステートメントを追加するとreturn jobs_list.count うまくいきます。おかげで
tylerSF

この回答の最初のソリューションは使用しないでください。テーブルビューのデータソースメソッドは、想定されている以上のことをしてはなりません。numberOfSectionsカウントを返す必要があり、それだけです。も同じですnumberOfRowsInSection。これらはいつでも何度でも呼び出すことができます。ビューを更新したり、データを更新したり、カウントを返す以外のことを行ったりしないでください。ビューを更新するロジックがこれらのメソッドに含まれていてはなりません。
rmaddy

6

このコントロールを試すことができます。それはかなりすっきりしています。DZNEmptyDataSet

または私があなたなら私がするすべては

  • データ配列が空かどうかを確認します
  • 空の場合、@ "No Data"というオブジェクトを1つ追加します
  • その文字列を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

同意する。このソリューションは改善できますが、使用することもできます。
テオドールシウラル

このソリューションを使用するべきではないが、使用できるということをどのようにして同意できますか?それは矛盾です。
rmaddy

このソリューションは改善できることに同意しますが、現在の状態でも機能します。
テオドールシウラル

5

Swift3.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 UITableViewControllerからUIViewControllerを含むに切り替えることだと思います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

テーブルビューフッターを使用せず、テーブルビューで画面をデフォルトの空のセルで埋めたくない場合は、テーブルビューフッターを空の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、ストーリーボードまたはxibsのさまざまなシーンのさまざまな空の状態テキストを変更できるようになります。楽しい!:)
Egist Li

1

テーブルビューに結果がない場合は、必要な外観とメッセージを持つオーバーレイビューを表示します。ViewDidAppearでそれを行うことができるので、ビューを表示/非表示する前に結果が得られます。


1

コードなしでこれを実行したい場合は、これを試してください!

tableViewをクリックします。

tableViewスクリーンショット

スタイルを「プレーン」から「グループ化」に変更します。

テーブルビューのプロパティのスクリーンショット2

今使用すると...

tableView.backgroundView =ラベルまたはビューを挿入

セパレータは表示されません!


1

このコードを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
  }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.