Boş bir UITableView işleme. Dostça bir mesaj yazdırın


124

Bazı durumlarda boş olmanın yasal olduğunu belirten bir UITableView var. Bu nedenle, uygulamanın arka plan resmini göstermek yerine ekranda aşağıdaki gibi dostça bir mesaj yazdırmayı tercih ederim:

Bu liste artık boş

Bunu yapmanın en basit yolu nedir?


10
Bu projeye göz atın: github.com/dzenbot/DZNEmptyDataSet
oleynikd

@oleynikd Teşekkürler !!!!!
Luda

Yanıtlar:


173

UITableView'ın backgroundView özelliği arkadaşınızdır.

Gelen viewDidLoadveya herhangi bir yerde sen misin reloadDataorada senin tablo boş olup olmadığını belirlemek ve bir UILabel içeren bir UIView ile UITableView en backgroundView özelliğini güncellemek ya da sadece nil ayarlayın gerekir. Bu kadar.

Elbette UITableView'ın veri kaynağının çift görev yapmasını ve özel bir "liste boş" hücresi döndürmesini sağlamak mümkün, bu beni bir kludge olarak etkiliyor. Birdenbire numberOfRowsInSection:(NSInteger)section, boş olduklarından emin olmak için sorulmayan diğer bölümlerin satır sayısını hesaplaması gerekir. Ayrıca boş mesajın olduğu özel bir hücre yapmalısınız. Ayrıca boş mesajı yerleştirmek için muhtemelen hücrenizin yüksekliğini değiştirmeniz gerektiğini de unutmayın. Bunların hepsi yapılabilir, ancak yara bandının yanı sıra yara bandı gibi görünüyor.


12
Bence en iyi çözüm backgroundView. Teşekkür ederim!
Ferran Maylinch

1
Bir dezavantaj, tablo görünümü aşağıya çekildiğinde mesajın konumunda kalmasıdır. Güncellemeler altında uygulama mağazası uygulamasında beğenilmeyi tercih ederim. İşte boş mesaj kaydırma davranışıyla birlikte ...
test

@testing Açıkçası, kaydırmak için boş mesajlaşmaya ihtiyacınız varsa, kaydırma hiyerarşisinin bir parçası olmadığı için arka plan görünümünü kullanamazsınız. Muhtemelen boş durum için özel bir bölüm ve UITableViewCell kullanmak istiyorsunuz.
LightningStryk

Geçiş backgroundViewgizli özellik gitmek yoludur. İle DZNEmptyDataSet,emptyDataSetSource
onmyway133

Düğmeler eklemek istiyorsanız, şunu yapmanız gerekir: tableView.backgroundView!.userInteraction = trueayarladığınız satırdan sonra tableView.backgroundView = constructMyViewWithButtons()veya nasıl ayarladığınız.
kbpontius

90

Jhonston'ın cevabıyla aynı, ancak bir uzantı olarak tercih ettim:

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

Kullanımı:

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
}

Öneriniz için teşekkür ederiz.
ssowri1

1
Uzatma daha iyidir! Teşekkürler.
Ogulcan Orhan

Uzantıyı seviyorum :)
Alix

1
Eğer bölümler varsa, o zaman bu mantığı taşımak gerekir func numberOfSections(in tableView: UITableView) -> Intyöntem
zanaat

87

Buradaki cevaplara dayanarak, işte kullanabileceğiniz hızlı bir ders 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;
    }
}

Gözlerinde farklı UITableViewControllersen bu çağırabilirsiniznumberOfSectionsInTableView(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
    }
}

görüntü açıklamasını buraya girin

Http://www.appcoda.com/pull-to-refresh-uitableview-empty/ adresinden küçük bir yardımla


yine de resim eklemek ister. Ama harika bir hızlı çözüm.
AnBisw

10
sınıf yerine bir uzantı kullanın (görüntü denetleyicisini geçmeyin)
Cesare

Yukarıdaki kodu benim için çalışacak şekilde alamadım, ancak diğerlerinin de aynı sorunu yaşaması durumunda, bu cevaptaki (ilki) kodu çalıştırmayı başardım. Ayrıca 2. cevabın da işe yarayacağını düşünüyorum (sahne yuvasını kullanarak) - stackoverflow.com/questions/28532926/…
Renee Olson

viewController.tableView.separatorStyle = .nonegerekli değildir.
Dmitry

17

Şu kitaplığı tavsiye ederim: DZNEmptyDataSet

Projenize eklemenin en kolay yolu, onu şu şekilde Cocaopod'larla kullanmaktır: pod 'DZNEmptyDataSet'

TableViewController'ınızda aşağıdaki içe aktarma ifadesini (Swift) ekleyin:

import DZNEmptyDataSet

Sonra mutlaka sınıf uyan, yapmak DNZEmptyDataSetSourceve DZNEmptyDataSetDelegateşöyle:

class MyTableViewController: UITableViewController, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate

Gözlerinde farklı viewDidLoadkod aşağıdaki satırları ekleyin:

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

Şimdi boş durumu göstermek için yapmanız gereken tek şey:

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

Bu yöntemler zorunlu değildir, boş durumu bir düğme olmadan göstermek de mümkündür.

Swift 4 için

// 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'in dikey olarak düzgün hizalanmamasıyla ilgili sorunlar yaşıyorum. Aynı sorunu yaşayan var mı?
amariduran

12

Bunu yapmanın bir yolu, veri kaynağınızı 1satır sayısı sıfır olduğunda geri gelecek şekilde değiştirmek ve tableView:cellForRowAtIndexPath:yöntemde özel amaçlı bir hücre (belki farklı bir hücre tanımlayıcısıyla) oluşturmaktır .

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

Bakım yapmanız gereken birden çok tablo görünümü denetleyiciniz varsa, bu biraz karmaşık olabilir, çünkü birileri sonunda sıfır kontrolü eklemeyi unutacaktır. Daha iyi bir yaklaşım, UITableViewDataSourceher zaman yapılandırılabilir bir mesajla tek bir satır döndüren bir uygulamanın ayrı bir uygulamasını oluşturmaktır (hadi çağıralım EmptyTableViewDataSource). Tablo görünümü denetleyiciniz tarafından yönetilen veriler değiştiğinde, değişikliği yöneten kod verilerin boş olup olmadığını kontrol eder. Boş değilse, tablo görünümü denetleyicinizi normal veri kaynağıyla ayarlayın; aksi takdirde, EmptyTableViewDataSourceuygun mesajla yapılandırılmış olanın bir örneğiyle ayarlayın .


5
deleteRowsAtIndexPaths:withRowAnimation:Döndürülen sayı numberOfRowsInSection$ numRows - $ rowsDeleted sonucuyla eşleşmesi gerektiğinden , satırları silinen tablolarda bunu yaparken sorunlar yaşadım .
Animal451

4
Buna karşı şiddetle tavsiye ederim. Kodunuzu uç durumlarla karıştırır.
xtravar

2
@xtravar Olumsuz oy kullanmak yerine, kendi cevabınızı yayınlamayı düşünün.
dasblinkenlight

1
Ben o yoldan gittim ve kendi sorunlarına yol açar. Deneyimlerime göre, Apple API'lerini yenilemek, onları değiştirmeye çalışmaktan neredeyse her zaman daha iyidir.
xtravar

1
Bu çözüm NSFetchedResultsController ile çalışmayacaktır. Bunun yerine backgroundView yaklaşımını deneyeceğim.
Sam

10

Bunun için titleForFooterInSection mesajını kullanıyorum. Bunun yetersiz olup olmadığını bilmiyorum ama işe yarıyor.

-(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
Güzel numara ve bana oldukça temiz görünüyor. İşte tek return tableView.numberOfRowsInSection(section) == 0 ? "This list is now empty" : nil
hat

8

Daha güvenli bir çözüm için:

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

ve UICollectionViewayrıca:

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

Daha Genel Çözüm:

    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

Yalnızca hücrelerden sonra TableView içine bir UITextView sürükleyip bırakmanızı tavsiye edebilirim. ViewController ile bir bağlantı kurun ve uygun olduğunda gizleyin / gösterin (örneğin, tablo her yeniden yüklendiğinde).

görüntü açıklamasını buraya girin


Bu en kolay yol)!
moonvader

Böyle acı verici bir baş ağrısı elma yolu; bu fikir için teşekkürler
Eenvincible

5

BackgroundView'ı kullanmak iyidir, ancak Mail.app'deki gibi hoş bir şekilde kaydırılmaz.

Xtravar'ın yaptığına benzer bir şey yaptım.

Görünüm hiyerarşisinin dışında bir görünüm ekledim tableViewController. hiyerarşi

Sonra aşağıdaki kodu kullandım 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

Temel emptyStateViewolarak tableViewnesneyi alt görünümü olarak ekledim . Ayırıcılar görünümle örtüştüğü için renklerini olarak ayarlıyorum clearColor. Varsayılan ayırıcı rengine geri dönmek için, olarak ayarlayabilirsiniz nil.


Bu oldukça iyi çalışıyor! Ancak yenilemek için çekme öğeleriniz varsa, örneğin, bu onlarla birlikte kaymaz. Ayarlamayı tableHeaderViewve sığacak şekilde yeniden boyutlandırmayı daha iyi buldum .
Hannele

4

Bir Container View Controller kullanmak, Apple'a göre bunu yapmanın doğru yoludur .

Tüm boş durum görünümlerimi ayrı bir Storyboard'a koyuyorum. Her biri kendi UIViewController alt sınıfı altında. İçeriği doğrudan kök görünümlerinin altına ekliyorum. Herhangi bir işlem / düğmeye ihtiyaç duyulursa, artık bunu halletmek için bir denetleyiciniz var.
Daha sonra, istenen görünüm denetleyicisini bu Storyboard'dan örneklemek, onu bir alt görünüm denetleyicisi olarak eklemek ve kapsayıcı görünümünü tableView hiyerarşisine (alt görünüm) eklemek yeterlidir. Boş durum görünümünüz de kaydırılabilir, bu da iyi hissettirir ve yenilemek için çekme uygulamanıza izin verir.

Nasıl uygulanacağıyla ilgili yardım için 'İçeriğinize Çocuk Görünümü Denetleyicisi Ekleme' bölümünü okuyun .

Sadece çocuk görünümü çerçevesini ayarladığınızdan emin olun, (0, 0, tableView.frame.width, tableView.frame.height)her şey ortalanacak ve düzgün şekilde hizalanacaktır.


3

Birincisi, diğer popüler yaklaşımlarla ilgili sorunlar.

BackgroundView

Bir UILabel olarak ayarlamanın basit durumunu kullanırsanız, arka plan görünümü güzel bir şekilde ortalanmaz.

Mesajı görüntülemek için hücreler, başlıklar veya alt bilgiler

Bu, işlevsel kodunuza müdahale eder ve garip uç durumları ortaya çıkarır. Mesajınızı mükemmel bir şekilde ortalamak istiyorsanız, bu başka bir karmaşıklık düzeyi ekler.

Kendi tablo görünümü denetleyicinizi yuvarlama

RenewControl gibi yerleşik işlevleri kaybedersiniz ve tekerleği yeniden icat edersiniz. Bakımı en iyi sonuçlar için UITableViewController'a bağlı kalın.

UITableViewController'ı alt görünüm denetleyicisi olarak ekleme

İOS 7+ sürümünde içerik yerleştirme sorunları yaşayacağına dair bir his var - artı neden işleri karmaşıklaştırasın?

Çözümüm

Bulduğum en iyi çözüm (ki bu ideal değil) bir kaydırma görünümünün üstüne oturup buna göre hareket edebilecek özel bir görünüm oluşturmaktır. Bu, iOS 7'de contentInset deliliği nedeniyle açıkça karmaşıklaşıyor, ancak yapılabilir.

Dikkat etmeniz gereken şeyler:

  • tablo ayırıcıları reloadData sırasında bir noktada öne çıkarılır - buna karşı korunmanız gerekir
  • contentInset / contentOffset - özel görünümünüzde bu anahtarları gözlemleyin
  • klavye - klavyenin size engel olmasını istemiyorsanız, bu başka bir hesaplama
  • otomatik düzen - görünümünüzü konumlandırmak için çerçeve değişikliklerine güvenemezsiniz

Bunu bir UIView alt sınıfında bir kez anladıktan sonra, onu her şey için kullanabilirsiniz - çarkları yüklemek, görünümleri devre dışı bırakmak, hata mesajlarını göstermek vb.


Cevabınızı detaylandırır mısınız? Masanın boş olup olmadığını nasıl anlarsınız? O zaman "buna göre hareket et".
Michael Ozeryansky

Masanızın boş olduğunu biliyorsunuz çünkü masanızı dolduran sizsiniz. Dolayısıyla, görünüm denetleyicinizde, eşzamansız bir yükleme geri çağrınız olur. Bu geri aramada, if (itemsToShow.count == 0) {görünümünüzü kaydırma görünümüne ekleyin}. İşin zor kısmı, üst görünümü ('kalkan / mesaj görünümü') kaydırma görünümünün tüm çerçevesini, eksi contentInset, vb. Kapsayacak şekilde konumlandırarak mesajın dikey olarak ortalanmasını sağlamaktır.
xtravar

Tablo görünümünün üstüne nasıl bir görünüm eklersiniz? self.view, tablo görünümüdür ve kullanırsam addSubView, otomatik mizanpajda her zaman sorunlara neden olan tablo görünümüne eklenir.
test

Tablo görünümüne yerleştirdiğiniz görünüm otomatik düzen kullanmamalıdır ve tablo görünümünün kendisi otomatik düzen kullanmaz.
xtravar

1
Orada bir yaklaşımı kaçırdınız; Bir UITableViewController kullanabilir ve onu normal bir UIViewController'a çocuk görüntüleme denetleyicisi olarak ekleyebilirsiniz
user1169629

3

Bu en iyi ve basit çözümdür.

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

Boş liste için Mesaj göster, Wether onun UITableView veya 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
        }
    }
}

Usages:

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

VEYA:

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

Unutmayın: Yenilemeden sonra verilerin gelmesi durumunda mesaj etiketini kaldırmayı unutmayın.



1

Film şeridinde tablo görünümünüzü Denetleyici Sahnesi seçin

görüntü açıklamasını buraya girin

UIVgörüntülemeyi sürükleyip bırakın Mesajınıza etiket ekleyin (örneğin: Veri Yok)

görüntü açıklamasını buraya girin

TableViewController'ınızda UIView çıkışını (örneğin yournoDataView için söyleyin) oluşturun.

ve viewDidLoad

self.tableView.backgroundView = yourNoDataView


1

Swift 4.2 kullanımı

  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

Bunu Base sınıfınıza ekleyebilirsiniz.

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'den veri alma konusunda sınıfta bunu böyle gösterin.

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

Bunu böyle sakla.

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

func hideNoDataMessage(){
    messageLabel.removeFromSuperview()
}

Hey @ Mudassir-Asghar hideNoDataMessage işlevi neye benziyor?
Saamer

1
Merhaba @ Saamer, yukarıdaki cevabı güncelledim. işaret ettiğiniz için teşekkürler, umarım bu yardımcı olur :)
Mudassir Asghar

0

Hızlı versiyon ama daha iyi ve daha basit bir form. ** 3.0

Umarım amacınıza hizmet eder ......

UITableViewController'ınızda.

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

İşlevli Yardımcı Sınıf:

 /* 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

Muhtemelen en iyi çözüm değil, ama bunu sadece masamın altına bir etiket koyarak ve satırlar = 0 ise ona bir metin atayarak yaptım. Oldukça kolaydır ve birkaç satır kodla yapmaya çalıştığınız şeyi başarır.

Masamda iki bölüm var (işler ve okullar)

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

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

İsterseniz, etiketi sayı = 0 olduğunda boş bir görüntü görünümüyle de değiştirebilirsiniz ..
Zach,

0

Bunu yapmanın en kolay ve en hızlı yolu, bir etiketi tableView altındaki yan panele sürüklemektir. Etiket ve tableView için bir çıkış oluşturun ve gerektiğinde etiketi ve tabloyu gizlemek ve göstermek için bir if ifadesi ekleyin. Alternatif olarak, tablo ve arka plan görünümü aynı renge sahipse boş bir tabloya gizli olduğu algısını vermek için bunu size viewDidLoad () için tableView.tableFooterView = UIView (çerçeve: CGRect.zero) ekleyebilirsiniz.


(Bu gönderi soruya kaliteli bir yanıt sağlamıyor gibi görünüyor . Lütfen cevabınızı düzenleyin ve daha ayrıntılı bilgilerle doldurun veya soruya yorum olarak gönderin).
sɐunıɔ ןɐ qɐp

0

Sayımı manuel olarak kontrol etmemiz için birkaç değişiklik yaptım, ayrıca etiket için kısıtlamalar ekledim, böylece aşağıda gösterildiği gibi mesaj ne kadar büyük olursa olsun hiçbir şey ters gitmeyecek:

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

kullanım

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.