空のUITableViewの処理。親しみやすいメッセージを印刷する


124

私はUITableViewを持っていますが、場合によっては空にすることもできます。そのため、アプリの背景画像を表示する代わりに、次のようなわかりやすいメッセージを画面に印刷したいと思います。

このリストは空です

それを行う最も簡単な方法は何ですか?


10
このプロジェクトを確認してください:github.com/dzenbot/DZNEmptyDataSet
oleynikd

@oleynikdありがとうございます!!!!!
ルダ、

回答:


173

UITableViewのbackgroundViewプロパティはあなたの友達です。

その中viewDidLoadまたはどこでもreloadData、テーブルが空かどうかを判断し、UILabelを含むUIViewでUITableViewのbackgroundViewプロパティを更新するか、単にnilに設定する必要があります。それでおしまい。

もちろん、UITableViewのデータソースに二重の役割を持たせ、特別な「リストが空」のセルを返すようにすることもできます。突然numberOfRowsInSection:(NSInteger)section、他のセクションの行数も計算する必要があり、行が空であることを確認することも求められませんでした。また、メッセージが空の特別なセルを作成する必要があります。また、おそらく空のメッセージに対応するためにセルの高さを変更する必要があることを忘れないでください。これはすべて実行可能ですが、バンドエイドの上にバンドエイドがあるようです。


12
backgroundViewが最良のソリューションだと思います。ありがとうございました!
Ferran Maylinch 2014年

1
1つの欠点は、テーブルビューがプルダウンされると、メッセージがその位置に留まることです。私はアップデートの下でアプリストアアプリのようにしたいのですが。ここでは、空のメッセージは...スクロール動作で行く
テスト

@testingもちろん、スクロールするために空のメッセージが必要な場合は、スクロール階層の一部ではないため、バックグラウンドビューを使用できません。空の状態には、カスタムセクションと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
延長の方がいいです!ありがとう。
オグルカンオルハン

拡張機能が大好きです:)
Alix

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 2017年

10
クラスの代わりに拡張機能を使用する(ビューコントローラを渡さない)
Cesare

私は上記のコードを機能させることができませんでしたが、他の人が同じ問題を抱えている場合に備えて、この回答のコード(最初のコード)を機能させることができました。また、私は第二答えは(シーンドックを使用して)、同様に働くだろうと思います- stackoverflow.com/questions/28532926/...
レニー・オルソン

viewController.tableView.separatorStyle = .none必須ではありません。
ドミトリー

17

次のライブラリをお勧めします:DZNEmptyDataSet

プロジェクトに追加する最も簡単な方法は、次のようにCocaopodsで使用することです。 pod 'DZNEmptyDataSet'

TableViewControllerに次のインポートステートメント(Swift)を追加します。

import DZNEmptyDataSet

その後に必ずあなたのクラスの適合を作るDNZEmptyDataSetSourceと、DZNEmptyDataSetDelegateそのように:

class MyTableViewController: UITableViewController, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate

あなたにはviewDidLoad次のコード行を追加します。

tableView.emptyDataSetSource = self
tableView.emptyDataSetDelegate = self
tableView.tableFooterView = UIView()

emptystateを表示するために必要なのは次のとおりです。

//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つの方法は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
$ numRows-$ rowsDeletedの結果と一致する必要があるためdeleteRowsAtIndexPaths:withRowAnimation:、行が削除されたテーブルでこれを行うと問題が発生しましたnumberOfRowsInSection
Animal451 2014年

4
私はこれに対して強くお勧めします。それはあなたのコードをエッジケースでだらします。
xtravar 2014年

2
@xtravar反対票を投じるのではなく、独自の回答を投稿することを検討してください。
dasblinkenlight 2014年

1
私はその道を進んでおり、それ自体がさまざまな問題を引き起こしています。私の経験では、ほとんどの場合、Apple APIを拡張する方が、置き換えるよりも優れています。
xtravar 2014年

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

セルの後のTableView内にUITextViewをドラッグアンドドロップすることのみをお勧めします。ViewControllerへの接続を作成し、必要に応じて(たとえば、テーブルがリロードされるたびに)非表示/表示します。

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


それが最も簡単な方法です)!
ムーンベイダー2016

リンゴのように痛い頭痛。このアイデアへの感謝
環境に優しい

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それに合わせてサイズ変更することを確認します
Hannele 2017年

4

Appleによると、Container View Controllerを使用するのが正しい方法です。

空の状態ビューをすべて別のストーリーボードに配置しました。その下には、それぞれ独自のUIViewControllerサブクラスがあります。ルートビューの直下にコンテンツを追加します。アクション/ボタンが必要な場合は、すでにそれを処理するコントローラーがあります。
次に、そのStoryboardから目的のビューコントローラーをインスタンス化し、それを子ビューコントローラーとして追加し、コンテナービューをtableViewの階層(サブビュー)に追加します。空の状態ビューもスクロール可能になります。これは快適で、プルトゥリフレッシュを実装できます。

実装方法については、「コンテンツへの子ビューコントローラの追加」のをお読みください

ちょうど子ビューフレームを設定する (0, 0, tableView.frame.width, tableView.frame.height)と、物事は中央に配置され、適切に配置されます。


3

まず、他の一般的なアプローチの問題。

BackgroundView

UILabelに設定するという単純なケースを使用すると、背景ビューは適切に中央に配置されません。

メッセージを表示するためのセル、ヘッダー、またはフッター

これは機能コードに干渉し、奇妙なエッジケースを引き起こします。メッセージを完全に中央に配置したい場合は、さらに複雑になります。

独自のテーブルビューコントローラーをロールする

refreshControlなどの組み込み機能を失い、ホイールを再発明します。維持可能な最良の結果を得るには、UITableViewControllerを使用してください。

子ビューコントローラーとしてUITableViewControllerを追加する

iOS 7以降でcontentInsetの問題が発生するような気がします。なぜ複雑なのでしょうか。

私の解決策

私が思いついた最善の解決策(そして当然のことながら、これは理想的ではありません)は、スクロールビューの上に座ってそれに応じて動作できる特別なビューを作成することです。これは明らかにiOS7ではcontentInsetの狂気で複雑になりますが、それは可能です。

注意しなければならないこと:

  • reloadData中のある時点でテーブルセパレータが前面に表示されます-これを防ぐ必要があります
  • contentInset / contentOffset-特別なビューでこれらのキーを観察します
  • キーボード-キーボードが邪魔になりたくない場合は、別の計算です
  • 自動レイアウト-フレームの変更に依存してビューを配置することはできません

これを1つのUIViewサブクラスで一度把握したら、スピナーのロード、ビューの無効化、エラーメッセージの表示など、すべてに使用できます。


答えを詳しく説明してください。テーブルが空かどうかはどうやってわかりますか?その後、「それに応じて行動する」。
Michael Ozeryansky、2014年

あなたがあなたのテーブルにデータを投入しているので、あなたはあなたのテーブルが空であることを知っています。したがって、ビューコントローラーでは、非同期読み込みコールバックがあります。そのコールバックでは、if(itemsToShow.count == 0){ビューをスクロールビューに追加します}。トリッキーな部分は、メッセージが垂直方向の中央に配置されるように、コンテンツビューを除いたスクロールビューのフレーム全体を占めるように配置されたトップビュー(「シールド/メッセージビュー」)を作成することです。
xtravar 2014年

テーブルビューの上にビューをどのように追加しますか?self.viewはテーブルビューであり、使用するaddSubViewと、自動レイアウトで常に問題となるテーブルビューにアタッチされます。
テスト

テーブルビュー内に配置するビューは自動レイアウトを使用しないでください。テーブルビュー自体は自動レイアウトを使用しません。
xtravar 2014年

1
そこでは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 {show}
Eddwin Paz

1

ストーリーボードでtableviewControllerシーンを選択します

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

UIView Add label with your message(eg:No Data)をドラッグアンドドロップ

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

TableViewControllerにUIViewのアウトレット(たとえばyournoDataViewなど)を作成します。

そして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さん、hideNoDataMessage関数はどのようなものですか?
Saamer

1
こんにちは、@ Saamer私は上の答えを更新しました。それを指摘してくれてありがとう、これが役に立てば幸い:)
Mudassir Asghar

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

0

おそらく最高の解決策ではありませんが、テーブルの下部にラベルを付けるだけでこれを行いました。行が0の場合は、テキストを割り当てます。かなり簡単で、数行のコードで実行しようとしていることを実現できます。

テーブルに2つのセクションがあります(仕事と学校)

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    if (jobs.count == 0 && schools.count == 0) {
        emptyLbl.text = "No jobs or schools"
    } else {
        emptyLbl.text = ""
    }

また、空のImageViewのでラベルを置き換えることができたときに、カウント= 0、あなたが望むならば...
ザック

0

これを行う最も簡単で迅速な方法は、tableViewの下のサイドパネルにラベルをドラッグすることです。ラベルとtableViewのアウトレットを作成し、ifステートメントを追加して、必要に応じてラベルとテーブルを非表示および表示します。または、tableView.tableFooterView = UIView(frame:CGRect.zero)thisを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
    }

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