Menangani UITableView kosong. Cetak pesan yang ramah

124

Saya memiliki UITableView yang dalam beberapa kasus adalah legal untuk dikosongkan. Jadi, alih-alih menampilkan gambar latar belakang aplikasi, saya lebih suka mencetak pesan bersahabat di layar, seperti:

Daftar ini sekarang kosong

Apa cara termudah untuk melakukannya?

kategori
sumber
10
Lihat proyek ini: github.com/dzenbot/DZNEmptyDataSet
oleynikd
@oleynikd Terima kasih !!!!!
Luda

Jawaban:

173

Properti backgroundView UITableView adalah teman Anda.

Di viewDidLoadatau di mana pun reloadDataAnda harus menentukan apakah ada tabel Anda kosong atau tidak dan perbarui properti backgroundView UITableView dengan UIView yang berisi UILabel atau setel ke nil. Itu dia.

Hal ini tentu saja memungkinkan untuk membuat sumber data UITableView melakukan tugas ganda dan mengembalikan sel khusus "daftar kosong", itu menurut saya sebagai kludge. Tiba-tiba numberOfRowsInSection:(NSInteger)sectionharus menghitung jumlah baris dari bagian lain yang tidak diminta untuk memastikannya juga kosong. Anda juga perlu membuat sel khusus yang memiliki pesan kosong. Juga jangan lupa bahwa Anda mungkin perlu mengubah ketinggian sel Anda untuk mengakomodasi pesan kosong. Ini semua bisa dilakukan tetapi sepertinya plester di atas plester.

Ray Fix
sumber
12
Saya rasa backgroundView adalah solusi terbaik. Terima kasih!
Ferran Maylinch
1
Salah satu kelemahannya adalah jika tampilan tabel ditarik ke bawah, pesan tetap pada posisinya. Saya lebih suka aplikasi toko aplikasi sedang diperbarui. Di sini pesan kosong mengikuti perilaku pengguliran ...
menguji
@testing jelas jika Anda memerlukan pesan kosong untuk menggulir, Anda tidak dapat menggunakan tampilan latar belakang karena itu bukan bagian dari hierarki gulir. Anda mungkin ingin menggunakan bagian khusus dan UITableViewCell untuk keadaan kosong.
LightningStryk
Beralih backgroundViewproperti tersembunyi adalah cara terbaik. Dengan DZNEmptyDataSet, kita harus menggunakanemptyDataSetSource
onmyway133
Jika Anda ingin menambahkan tombol, Anda harus melakukan: tableView.backgroundView!.userInteraction = truesetelah baris Anda mengatur tableView.backgroundView = constructMyViewWithButtons(), atau bagaimanapun Anda mengaturnya.
kbpontius
90

Sama seperti jawaban Jhonston, tapi saya lebih suka sebagai perpanjangan:

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

Pemakaian:

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
}
Frankie
sumber
Terima kasih atas saranmu.
ssowri1
1
Perpanjangan lebih baik! Terima kasih.
Ogulcan Orhan
Suka ekstensi :)
Alix
1
Jika Anda memiliki bagian, maka Anda akan perlu untuk memindahkan logika ini ke func numberOfSections(in tableView: UITableView) -> Intmetode
kerajinan
87

Berdasarkan jawaban di sini, berikut adalah kelas singkat yang saya buat yang dapat Anda gunakan di 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;
    }
}

Dalam diri Anda, UITableViewControllerAnda dapat memanggil ininumberOfSectionsInTableView(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
    }
}

masukkan deskripsi gambar di sini

Dengan sedikit bantuan dari http://www.appcoda.com/pull-to-refresh-uitableview-empty/

Johnston
sumber
juga ingin menambahkan gambar ke dalamnya. Tapi solusi cepat yang bagus.
AnBisw
10
gunakan ekstensi sebagai ganti kelas (jangan berikan pengontrol tampilan)
Cesare
Saya tidak dapat membuat kode di atas berfungsi untuk saya, tetapi saya dapat membuat kode dalam jawaban ini (yang pertama) berfungsi, jika orang lain memiliki masalah yang sama. Juga saya pikir jawaban kedua akan bekerja juga (menggunakan dermaga adegan) - stackoverflow.com/questions/28532926/…
Renee Olson
viewController.tableView.separatorStyle = .nonetidak diperlukan.
Dmitry
17

Saya merekomendasikan perpustakaan berikut: DZNEmptyDataSet

Cara termudah untuk menambahkannya dalam proyek Anda adalah menggunakannya dengan Cocaopods seperti: pod 'DZNEmptyDataSet'

Di TableViewController Anda, tambahkan pernyataan import berikut (Swift):

import DZNEmptyDataSet

Kemudian pastikan kelas Anda sesuai dengan DNZEmptyDataSetSourcedan DZNEmptyDataSetDelegatesuka:

class MyTableViewController: UITableViewController, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate

Di viewDidLoadtambahkan baris kode berikut:

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

Sekarang yang harus Anda lakukan untuk menunjukkan keadaan kosong adalah:

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

Metode ini tidak wajib, juga memungkinkan untuk hanya menampilkan keadaan kosong tanpa tombol, dll.

Untuk 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)
}
Hapeki
sumber
Saya mengalami masalah dengan DZEmptyDataSet tidak sejajar secara vertikal dengan benar. Adakah yang punya masalah yang sama?
amariduran
12

Salah satu cara untuk melakukannya adalah memodifikasi sumber data Anda untuk ditampilkan 1ketika jumlah baris adalah nol, dan untuk menghasilkan sel tujuan khusus (mungkin dengan pengenal sel yang berbeda) dalam tableView:cellForRowAtIndexPath:metode.

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

Ini mungkin menjadi agak rumit jika Anda memiliki beberapa pengontrol tampilan tabel yang perlu Anda pertahankan, karena seseorang pada akhirnya akan lupa untuk menyisipkan cek nol. Pendekatan yang lebih baik adalah membuat implementasi terpisah dari UITableViewDataSourceimplementasi yang selalu mengembalikan satu baris dengan pesan yang dapat dikonfigurasi (sebut saja EmptyTableViewDataSource). Ketika data yang dikelola oleh pengontrol tampilan tabel Anda berubah, kode yang mengelola perubahan akan memeriksa apakah datanya kosong. Jika tidak kosong, setel pengontrol tampilan tabel Anda dengan sumber data regulernya; jika tidak, setel dengan instance EmptyTableViewDataSourceyang telah dikonfigurasi dengan pesan yang sesuai.

dasblinkenlight
sumber
5
Saya mengalami masalah melakukan ini dengan tabel yang barisnya dihapus deleteRowsAtIndexPaths:withRowAnimation:karena nomor yang dikembalikan dari numberOfRowsInSectionharus cocok dengan hasil $ numRows - $ rowDeleted.
Hewan451
4
Saya sangat, sangat merekomendasikan hal ini. Ini memecahkan kode Anda dengan case edge.
xtravar
2
@xtravar Daripada downvoting, pertimbangkan untuk memposting jawaban Anda sendiri.
dasblinkenlight
1
Saya telah melalui jalan itu, dan itu mengarah pada serangkaian masalahnya sendiri. Menurut pengalaman saya, menambahkan API Apple hampir selalu lebih baik daripada mencoba menggantinya.
xtravar
1
Solusi ini tidak akan berfungsi dengan NSFetchedResultsController. Saya akan mencoba pendekatan backgroundView sebagai gantinya.
Sam
10

Saya telah menggunakan pesan titleForFooterInSection untuk ini. Saya tidak tahu apakah ini suboptimal atau tidak, tetapi berhasil.

-(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;
}
Carlos B
sumber
2
Trik yang bagus dan tampaknya cukup bersih bagi saya. Ini satu baris:return tableView.numberOfRowsInSection(section) == 0 ? "This list is now empty" : nil
TruMan1
8

Jadi untuk solusi yang lebih aman:

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

dan untuk UICollectionViewjuga:

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

Solusi yang Lebih Umum:

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

Saya hanya dapat merekomendasikan untuk menyeret & menjatuhkan UITextView di dalam TableView setelah sel. Buat koneksi ke ViewController dan sembunyikan / tampilkan jika perlu (misalnya, setiap kali tabel dimuat ulang).

masukkan deskripsi gambar di sini

pasql
sumber
Itu cara termudah)!
moonvader
Sakit kepala yang menyakitkan seperti apel; terima kasih atas ide ini
Eenvincible
5

Menggunakan backgroundView baik-baik saja, tetapi tidak menggulir dengan baik seperti di Mail.app.

Saya melakukan sesuatu yang mirip dengan apa yang dilakukan xtravar .

Saya menambahkan tampilan di luar hierarki tampilan tableViewController. hirarki

Kemudian saya menggunakan kode berikut di 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

Pada dasarnya saya menambahkan emptyStateViewsebagai subview dari tableViewobjek. Karena pemisah akan tumpang tindih dengan tampilan, saya mengatur warnanya ke clearColor. Untuk kembali ke warna pemisah default, Anda bisa mengaturnya ke nil.

mangerlahn
sumber
Ini bekerja dengan cukup baik! Tetapi jika Anda memiliki elemen untuk menarik untuk menyegarkan misalnya, ini tidak menggulir bersama mereka. Saya merasa lebih baik untuk menyetelnya tableHeaderView, dan memastikan ukurannya berubah agar pas .
Hannele
4

Menggunakan Pengontrol Tampilan Kontainer adalah cara yang tepat untuk melakukannya sesuai dengan Apple .

Saya meletakkan semua pandangan keadaan kosong saya di Storyboard terpisah. Masing-masing di bawah subclass UIViewController miliknya sendiri. Saya menambahkan konten langsung di bawah tampilan root mereka. Jika ada tindakan / tombol yang diperlukan, Anda sekarang sudah memiliki pengontrol untuk menanganinya.
Maka itu hanya masalah membuat contoh pengontrol tampilan yang diinginkan dari Storyboard itu, menambahkannya sebagai pengontrol tampilan anak dan menambahkan tampilan kontainer ke hierarki tableView (sub tampilan). Tampilan status kosong Anda juga akan dapat di-scroll, yang terasa nyaman dan memungkinkan Anda menerapkan tarik untuk menyegarkan.

Baca bab 'Menambahkan Pengontrol Tampilan Anak ke Konten Anda' untuk bantuan tentang cara menerapkan.

Pastikan Anda menyetel bingkai tampilan anak sebagai (0, 0, tableView.frame.width, tableView.frame.height)dan semuanya akan dipusatkan dan disejajarkan dengan benar.

AmitP
sumber
3

Pertama, masalah dengan pendekatan populer lainnya.

BackgroundView

Tampilan latar belakang tidak berada di tengah dengan baik jika Anda menggunakan kasus sederhana untuk menyetelnya menjadi UILabel.

Sel, header, atau footer untuk menampilkan pesan

Ini mengganggu kode fungsional Anda dan menyebabkan kasus tepi yang aneh. Jika Anda ingin memusatkan pesan Anda dengan sempurna, itu menambah tingkat kerumitan lainnya.

Menggulung pengontrol tampilan tabel Anda sendiri

Anda kehilangan fungsionalitas bawaan, seperti refreshControl, dan menemukan kembali roda. Tetap gunakan UITableViewController untuk hasil terbaik yang dapat dirawat.

Menambahkan UITableViewController sebagai pengontrol tampilan anak

Saya merasa Anda akan berakhir dengan masalah contentInset di iOS 7+ - plus mengapa memperumit masalah?

Solusi saya

Solusi terbaik yang saya temukan (dan, memang, ini tidak ideal) adalah membuat tampilan khusus yang dapat duduk di atas tampilan gulir dan bertindak sesuai. Ini jelas menjadi rumit di iOS 7 dengan kegilaan contentInset, tetapi itu bisa dilakukan.

Hal-hal yang harus Anda perhatikan:

  • pemisah tabel dibawa ke depan di beberapa titik selama reloadData - Anda harus berhati-hati terhadapnya
  • contentInset / contentOffset - amati kunci tersebut pada tampilan khusus Anda
  • keyboard - jika Anda tidak ingin keyboard menghalangi, itu adalah perhitungan lain
  • autolayout - Anda tidak dapat bergantung pada perubahan bingkai untuk mengatur posisi tampilan Anda

Setelah Anda mengetahui ini sekali dalam satu subkelas UIView, Anda dapat menggunakannya untuk semuanya - memuat spinner, menonaktifkan tampilan, menampilkan pesan kesalahan, dll.

xtravar.dll
sumber
Bisakah Anda menjelaskan jawaban Anda. Bagaimana Anda mengetahui jika tabel kosong? Untuk kemudian "bertindak sesuai".
Michael Ozeryansky
Anda tahu bahwa tabel Anda kosong karena Andalah yang mengisi tabel Anda. Jadi di pengontrol tampilan, Anda akan memiliki callback pemuatan asinkron. Dalam callback tersebut, if (itemsToShow.count == 0) {add your view to the scroll view}. Bagian rumitnya adalah membuat tampilan atas ('tampilan perisai / pesan') diposisikan untuk mengambil seluruh bingkai tampilan gulir, dikurangi contentInset, dll., Sehingga pesan dipusatkan secara vertikal.
xtravar
Bagaimana Anda menambahkan tampilan di atas tampilan tabel? self.view adalah tampilan tabel dan jika saya menggunakannya addSubViewakan dilampirkan ke tampilan tabel yang selalu membuat masalah dengan tata letak otomatis.
menguji
Tampilan yang Anda tempatkan dalam tampilan tabel tidak boleh menggunakan tata letak otomatis, dan tampilan tabel itu sendiri tidak menggunakan tata letak otomatis.
xtravar
1
Anda melewatkan satu pendekatan di sana; Anda bisa menggunakan UITableViewController dan menambahkannya sebagai pengontrol tampilan anak ke UIViewController biasa
user1169629
3

Ini adalah solusi terbaik dan sederhana.

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;
Rajesh Maurya
sumber
2

Tampilkan Pesan untuk daftar kosong, Apakah UITableView atau UICollectionView-nya .

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

Penggunaan:

if cellsViewModels.count == 0 {
    self.tableView.showEmptyListMessage("No Product In List!")
}

ATAU:

if cellsViewModels.count == 0 {
    self.collectionView?.showEmptyListMessage("No Product In List!")
}

Ingat: Jangan lupa untuk menghapus label pesan jika data akan datang setelah refresh.

Gurjit Singh
sumber
1
Saya akan menambahkan kondisi if if messages.count! = 0 {show}
Eddwin Paz
1

Pilih Scene tableviewController Anda di storyboard

masukkan deskripsi gambar di sini

Seret dan lepas UIView Tambahkan label dengan pesan Anda (misalnya: Tidak Ada Data)

masukkan deskripsi gambar di sini

buat outlet UIView (katakanlah misalnya yournoDataView) di TableViewController Anda.

dan di viewDidLoad

self.tableView.backgroundView = yourNoDataView

gaurav bhardwaj
sumber
1

Menggunakan 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
}
M Murteza
sumber
1

Anda dapat menambahkan ini ke kelas Base Anda.

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

Tunjukkan seperti ini di kelas untuk mendapatkan data dari api.

func populateData(dataSource : [PRNJobDataSource]){
    self.dataSource = dataSource
    self.tblView.reloadData()
    if self.dataSource.count == 0 {self.showNoDataMessage(msg: "No data found.")}
}

Sembunyikan seperti ini.

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if self.dataSource.count > 0 {self.hideNoDataMessage()}
    return dataSource.count
}

func hideNoDataMessage(){
    messageLabel.removeFromSuperview()
}
Mudassir Asghar
sumber
Hai @ Mudassir-Asghar seperti apa fungsi hideNoDataMessage?
Saamer
1
Hai, @Saamer saya baru saja memperbarui jawaban di atas. terima kasih telah menunjukkannya, semoga ini membantu :)
Mudassir Asghar
0

Versi cepat tetapi bentuk yang lebih baik dan lebih sederhana. ** 3.0

Saya berharap itu sesuai dengan tujuan Anda ......

Di UITableViewController Anda.

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

Kelas Pembantu dengan fungsi:

 /* 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;
        }
Ravindra Shekhawat
sumber
0

Mungkin bukan solusi terbaik, tetapi saya melakukan ini dengan hanya meletakkan label di bagian bawah tabel saya dan jika baris = 0 maka saya menetapkannya beberapa teks. Cukup mudah, dan mencapai apa yang Anda coba lakukan dengan beberapa baris kode.

Saya memiliki dua bagian di tabel saya (pekerjaan dan sekolah)

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

    if (jobs.count == 0 && schools.count == 0) {
        emptyLbl.text = "No jobs or schools"
    } else {
        emptyLbl.text = ""
    }
Zach
sumber
Anda juga dapat mengganti label dengan imageview kosong ketika count = 0 jika Anda ingin ..
Zach
0

Cara termudah dan tercepat untuk melakukannya adalah dengan menyeret label ke panel samping di bawah tableView. Buat outlet untuk label dan tableView dan tambahkan pernyataan if untuk menyembunyikan dan menampilkan label dan tabel sesuai kebutuhan. Atau Anda dapat menambahkan tableView.tableFooterView = UIView (frame: CGRect.zero) ini kepada Anda viewDidLoad () untuk memberikan persepsi pada tabel kosong bahwa ia tersembunyi jika tampilan tabel dan latar belakang memiliki warna yang sama.

yoamod
sumber
(Posting ini tampaknya tidak memberikan jawaban berkualitas untuk pertanyaan. Harap edit jawaban Anda dan lengkapi dengan informasi yang lebih detail, atau cukup posting sebagai komentar untuk pertanyaan).
sɐunıɔ ןɐ qɐp
0

Saya membuat beberapa perubahan sehingga kita tidak perlu memeriksa hitungan secara manual, juga saya menambahkan batasan untuk label sehingga tidak ada yang salah tidak peduli seberapa besar pesannya seperti yang ditunjukkan di bawah ini:

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

Pemakaian

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let message: String = "The list is empty."
        ticketsTableView.setEmptyMessage(message, tickets.isEmpty)
        return self.tickets.count
    }
Kompiler alsh
sumber
0

Atau sebagai alternatif, Anda dapat menggunakan perpustakaan ringan yang dapat disesuaikan

SwiftEmptyState

Enes Karaosman
sumber