खाली UITableView को संभालना। एक मैसेज प्रिंट करें


124

मेरे पास एक UITableView है कि कुछ मामलों में खाली होना कानूनी है। इसलिए ऐप की पृष्ठभूमि छवि दिखाने के बजाय, मैं स्क्रीन में एक दोस्ताना संदेश प्रिंट करना पसंद करूंगा, जैसे:

यह सूची अब खाली है

इसे करने का सबसे सरल तरीका क्या है?


10
इस प्रोजेक्ट को देखें: github.com/dzenbot/DZNEmptyDataSet
oleynikd

@oleynikd धन्यवाद !!!!!
लुडा

जवाबों:


173

UITableView की पृष्ठभूमि दृश्य संपत्ति आपकी मित्र है।

इसमें viewDidLoadया कहीं भी reloadDataआपको यह निर्धारित करना चाहिए कि आपकी तालिका खाली है या नहीं और UITableView की पृष्ठभूमि दृश्य संपत्ति को UIView युक्त अपडेट करें या यूआईबेल युक्त करें या बस इसे शून्य पर सेट करें। बस।

यह निश्चित रूप से संभव है कि यूआईटेबल व्यू के डेटा स्रोत को डबल ड्यूटी करें और एक विशेष "सूची खाली है" सेल लौटाएं, यह मुझे एक कीचड़ के रूप में मारता है। अचानक numberOfRowsInSection:(NSInteger)sectionअन्य वर्गों की पंक्तियों की संख्या की गणना करने के लिए यह सुनिश्चित करने के बारे में नहीं पूछा गया था कि वे खाली हैं। आपको एक विशेष सेल बनाने की भी आवश्यकता है जिसमें खाली संदेश है। यह भी मत भूलो कि खाली संदेश को समायोजित करने के लिए आपको अपने सेल की ऊंचाई बदलने की आवश्यकता है। यह सब उल्लेखनीय है लेकिन यह बैंड-सहायता के शीर्ष पर बैंड-सहायता की तरह लगता है।


12
मुझे लगता है कि पृष्ठभूमि का दृश्य सबसे अच्छा समाधान है। धन्यवाद!
फेरन मायलिनच

1
एक नुकसान यह है कि यदि तालिका दृश्य को नीचे खींच लिया जाता है तो संदेश अपनी स्थिति पर रहता है। मैं अपडेट के तहत ऐप स्टोर ऐप में पसंद करना चाहता हूं। यहाँ खाली संदेश स्क्रॉल व्यवहार के साथ जाता है ...
परीक्षण

@ स्पष्ट रूप से यदि आपको स्क्रॉल करने के लिए रिक्त संदेश की आवश्यकता है तो आप पृष्ठभूमि दृश्य का उपयोग नहीं कर सकते क्योंकि यह स्क्रॉल पदानुक्रम का हिस्सा नहीं है। आप शायद खाली राज्य के लिए एक कस्टम अनुभाग और UITableViewCell का उपयोग करना चाहते हैं।
लाइटनिंगस्ट्रीक

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/ से थोड़ी मदद से


हालाँकि, इसमें छवि जोड़ना चाहेंगे। लेकिन एक महान त्वरित समाधान।
अनीब

10
क्लास के बजाय एक्सटेंशन का उपयोग करें (व्यू कंट्रोलर पास न करें)
Cesare

मुझे मेरे लिए काम करने के लिए उपरोक्त कोड नहीं मिल रहा था, लेकिन मैं इस उत्तर में कोड प्राप्त करने में सक्षम था (पहले वाला) काम करने के लिए, अगर अन्य को भी यही समस्या हो। इसके अलावा, मुझे लगता है कि दूसरा उत्तर भी काम करेगा (सीन डॉक का उपयोग करके) - stackoverflow.com/questions/28532926/…
रेनी ओल्सन

viewController.tableView.separatorStyle = .noneआवश्यकता नहीं है।
दिमित्री

17

मैं निम्नलिखित पुस्तकालय की सिफारिश करता हूं: DZNEmptyDataSet

अपनी परियोजना में इसे जोड़ने का सबसे आसान तरीका यह है कि इसे Cocaopods के साथ उपयोग करें: pod 'DZNEmptyDataSet'

अपने TableViewController में निम्नलिखित आयात विवरण जोड़ें (स्विफ्ट):

import DZNEmptyDataSet

फिर सुनिश्चित करें कि आपकी कक्षा के अनुरूप है DNZEmptyDataSetSourceऔर इस DZNEmptyDataSetDelegateतरह:

class MyTableViewController: UITableViewController, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate

अपने viewDidLoadकोड की निम्नलिखित पंक्तियों में जोड़ें:

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

अब आपको केवल यह दिखाना है कि खाली जगह क्या है:

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

ये विधियाँ अनिवार्य नहीं हैं, यह भी संभव है कि केवल एक बटन आदि के बिना खाली स्थिति दिखाएं।

स्विफ्ट 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जब पंक्तियों की संख्या शून्य हो, और 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
मुझे उन तालिकाओं के साथ ऐसा करने में समस्या हुई है जिनकी पंक्तियों को हटा दिया गया है deleteRowsAtIndexPaths:withRowAnimation:क्योंकि संख्याओं से numberOfRowsInSection$ numRows - $ rowDeleted के परिणाम से मिलान करने की आवश्यकता है।
पशुपालक

4
मैं इसके खिलाफ अत्यधिक सलाह देता हूं। यह आपके कोड को धारदार मामलों में बदल देता है।
xtravar

2
@xtravar डाउनवोटिंग के बजाय, अपना खुद का उत्तर पोस्ट करने पर विचार करें।
dasblinkenlight

1
मैं उस रास्ते से नीचे आ गया हूं, और यह समस्याओं की अपनी सरणी की ओर जाता है। मेरे अनुभव में, Apple API को बढ़ाने के बजाय उन्हें बदलने की कोशिश करना लगभग हमेशा बेहतर होता है।
xtravar

1
यह समाधान NSFetchedResultsController के साथ काम नहीं करेगा। मैं इसके बजाय पृष्ठभूमि दृश्य दृष्टिकोण की कोशिश करने जा रहा हूँ।
सैम

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

मैं केवल कक्षों के बाद तालिका दृश्य के अंदर एक UITextView को खींचने और छोड़ने की सिफारिश कर सकता हूं। ViewController के लिए एक कनेक्शन बनाएं और उचित होने पर इसे छिपाएं / प्रदर्शित करें (जैसे जब भी तालिका पुनः लोड होती है)।

यहाँ छवि विवरण दर्ज करें


यह सबसे आसान तरीका है)!
चंद्रवेद

सेब के रास्ते में ऐसा दर्दनाक सिरदर्द; इस विचार के लिए धन्यवाद
Eenvincible

5

बैकग्राउंड का उपयोग करना ठीक है, लेकिन यह 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 , और यह सुनिश्चित किया कि यह फिट करने के लिए आकार बदलता है
हैनले

4

कंटेनर व्यू कंट्रोलर का उपयोग करना Apple के अनुसार इसे करने का सही तरीका है ।

मैंने अपने सभी खाली राज्य के विचारों को एक अलग स्टोरीबोर्ड में रखा। इसके अंतर्गत प्रत्येक का अपना स्वयं का UIViewController उपवर्ग है। मैं सीधे उनके मूल दृश्य के तहत सामग्री जोड़ता हूं। यदि किसी कार्रवाई / बटन की आवश्यकता है, तो आपके पास अब पहले से ही इसे संभालने के लिए एक नियंत्रक है।
फिर यह स्टोरीबोर्ड से वांछित व्यू कंट्रोलर को इंस्टेंट करने की बात है, इसे चाइल्ड व्यू कंट्रोलर के रूप में जोड़ें और कंटेनर व्यू को टेबल व्यू के पदानुक्रम (सब व्यू) में जोड़ें। आपकी खाली स्थिति दृश्य के रूप में अच्छी तरह से स्क्रॉल होगी, जो अच्छा लगता है और आपको ताज़ा करने के लिए पुल को लागू करने की अनुमति देता है।

लागू करने के तरीके के बारे में मदद के लिए अध्याय 'अपनी सामग्री में एक बाल देखने वाला नियंत्रक जोड़ना' पढ़ें

बस यह सुनिश्चित करें कि आप बच्चे के दृश्य फ्रेम को सेट करते हैं (0, 0, tableView.frame.width, tableView.frame.height)और चीजें ठीक से केन्द्रित और संरेखित होंगी।


3

सबसे पहले, अन्य लोकप्रिय दृष्टिकोणों के साथ समस्याएं।

BackgroundView

यदि आप इसे यूआईबेल होने के लिए सेट करने के सरल मामले का उपयोग करना चाहते हैं तो पृष्ठभूमि दृश्य अच्छी तरह से केंद्र में नहीं है।

संदेश प्रदर्शित करने के लिए कक्ष, शीर्षलेख या पाद लेख

यह आपके कार्यात्मक कोड के साथ हस्तक्षेप करता है और अजीब धार मामलों का परिचय देता है। यदि आप अपने संदेश को पूरी तरह से केन्द्रित करना चाहते हैं, जो जटिलता के एक और स्तर को जोड़ता है।

अपने खुद के टेबल व्यू कंट्रोलर को रोल करना

आप अंतर्निहित कार्यक्षमता खो देते हैं, जैसे कि रिफ्रेशकंट्रोल, और पहिए का फिर से आविष्कार। सबसे अच्छा बनाए रखने के परिणामों के लिए UITableViewController के लिए छड़ी।

एक बच्चे को देखने के नियंत्रक के रूप में UITableViewController जोड़ना

मुझे लगता है कि आप iOS 7+ में contentInset मुद्दों के साथ समाप्त करेंगे - इसके अलावा चीजों को जटिल क्यों करें?

मेरा समाधान

मेरे द्वारा सबसे अच्छा समाधान (और, दी गई, यह आदर्श नहीं है) एक विशेष दृश्य बनाना है जो स्क्रॉल दृश्य के शीर्ष पर बैठ सकता है और तदनुसार कार्य कर सकता है। यह स्पष्ट रूप से iOS 7 में contentInset पागलपन के साथ जटिल हो जाता है, लेकिन यह संभव है।

जिन चीजों के लिए आपको देखना होगा:

  • तालिका विभाजक पुनः लोड के दौरान कुछ बिंदु पर सामने लाते हैं - आपको इसके खिलाफ पहरा देने की आवश्यकता है
  • contentInset / contentOffset - अपने विशेष दृश्य पर उन कुंजियों का निरीक्षण करें
  • कीबोर्ड - यदि आप नहीं चाहते कि कीबोर्ड रास्ते में आए, तो यह एक और गणना है
  • स्वतः पूर्णता - आप अपने दृश्य की स्थिति के लिए फ्रेम परिवर्तन पर निर्भर नहीं हो सकते

एक बार जब आप एक यूआईईवीई सबक्लास में एक बार यह पता लगा लेते हैं, तो आप इसे सब कुछ के लिए उपयोग कर सकते हैं - स्पिनरों को लोड करना, विचारों को अक्षम करना, त्रुटि संदेश दिखाना आदि।


क्या आप अपने जवाब में विस्तार से बता सकते हैं। अगर टेबल खाली है तो आप कैसे बताएंगे? तब तक "तदनुसार कार्य करें"।
माइकल ओजेरानस्की 23

आप जानते हैं कि आपकी तालिका खाली है क्योंकि आप अपनी तालिका को आबाद कर रहे हैं। आपके विचार नियंत्रक में, आपके पास एक अतुल्यकालिक लोडिंग कॉलबैक होगा। उस कॉलबैक में, यदि (आइटम्सटॉश.कोाउंट == 0) {स्क्रॉल दृश्य में अपना दृश्य जोड़ें}। पेचीदा हिस्सा उस शीर्ष दृश्य ('शील्ड / मैसेज व्यू') को स्क्रॉल व्यू, माइनस कंटेंट इनसेट, आदि के पूरे फ्रेम को लेने के लिए तैनात कर रहा है, ताकि संदेश लंबवत केंद्रित हो।
xtravar

आप तालिका दृश्य के शीर्ष पर एक दृश्य कैसे जोड़ते हैं? self.view टेबल व्यू है और अगर मैं इसका उपयोग addSubViewकरता हूं तो यह टेबल व्यू से जुड़ा हुआ है जो हमेशा ऑटो लेआउट के साथ समस्या बनाता है।
परीक्षण

तालिका दृश्य के भीतर आपके द्वारा देखा गया दृश्य ऑटोलाययूट का उपयोग नहीं करना चाहिए, और तालिका दृश्य में स्वतः पूर्णांक का उपयोग नहीं किया जाना चाहिए।
xtravar

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
मैं messages.count अगर एक अगर हालत जोड़ना होगा = {शो} 0!
Eddwin पाज़

1

स्टोरीबोर्ड में अपना टेबलव्यू कंट्रोलर सीन चुनें

यहाँ छवि विवरण दर्ज करें

अपने संदेश के साथ UIView लेबल जोड़ें और खींचें (जैसे: कोई डेटा नहीं)

यहाँ छवि विवरण दर्ज करें

अपने TableViewController पर UIView (जैसे उदाहरण के लिए yournoDataView) का आउटलेट बनाएं।

और देखने में

self.tableView.backgroundView = yourNoDataView


1

स्विफ्ट का उपयोग करना 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)
}

एपीआई से डेटा प्राप्त करने पर कक्षा में इसे इस तरह दिखाएं।

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

अरे @ मुदस्सिर-असगर क्या छुपता है NNDDataMessage फंक्शन कैसा दिखता है?
आमेर

1
नमस्ते, @ आमेर I ने केवल उपरोक्त उत्तर को अपडेट किया। इसे इंगित करने के लिए धन्यवाद, आशा है कि यह मदद करता है :)
मुदस्सिर असगर

0

स्विफ्ट संस्करण लेकिन बेहतर और सरल रूप। ** 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 तो मैं इसे कुछ पाठ निर्दिष्ट करता हूं। बहुत आसान है, और प्राप्त करता है कि आप कोड की कुछ पंक्तियों के साथ क्या करने की कोशिश कर रहे हैं।

मेरी तालिका में दो खंड हैं (नौकरी और स्कूल)

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

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

जब आप चाहते थे तो आप एक खाली इमेजव्यू के साथ लेबल को प्रतिस्थापित कर सकते हैं। 0 = यदि आप चाहते हैं ..
Zach

0

ऐसा करने का सबसे आसान और तेज तरीका है कि लेबल को साइड पैनल पर tableView के तहत खींचें। लेबल और तालिका दृश्य के लिए एक आउटलेट बनाएं और यदि आवश्यक हो तो लेबल और तालिका को छिपाने और दिखाने के लिए एक if स्टेटमेंट जोड़ें। वैकल्पिक रूप से आप tableView.tableFooterView = UIView (फ्रेम: CGRect.zero) को इसमें जोड़ सकते हैं ताकि आप खाली टेबल को यह देख सकें कि टेबल और बैकग्राउंड व्यू एक ही रंग के हैं या नहीं।


(यह पोस्ट प्रश्न का एक गुणवत्ता उत्तर प्रदान करने के लिए प्रतीत नहीं होता है । कृपया या तो अपने उत्तर को संपादित करें और इसे अधिक विस्तृत जानकारी के साथ पूरा करें, या बस इसे प्रश्न के लिए एक टिप्पणी के रूप में पोस्ट करें)।
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
    }

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.