Handling an empty UITableView. Print a friendly message

前端 未结 22 1053
青春惊慌失措
青春惊慌失措 2020-12-04 05:22

I have a UITableView that in some cases it is legal to be empty. So instead of showing the background image of the app, I would prefer to print a friendly message in the scr

相关标签:
22条回答
  • 2020-12-04 05:53

    I recommend the following library: DZNEmptyDataSet

    The easiest way to add it in your project is to use it with Cocaopods like so: pod 'DZNEmptyDataSet'

    In your TableViewController add the following import statement (Swift):

    import DZNEmptyDataSet
    

    Then make sure your class conforms to the DNZEmptyDataSetSource and DZNEmptyDataSetDelegate like so:

    class MyTableViewController: UITableViewController, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate
    

    In your viewDidLoad add the following lines of code:

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

    Now all you have to do to show the emptystate is:

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

    These methods aren't mandatory, it's also possible to just show the empty state without a button etc.

    For 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)
    }
    
    0 讨论(0)
  • 2020-12-04 05:55

    I can only recommend to drag&drop a UITextView inside the TableView after the cells. Make a connection to the ViewController and hide/display it when appropriate (e.g. whenever the table reloads).

    0 讨论(0)
  • 2020-12-04 05:55

    Using the backgroundView is fine, but it does not scroll nicely like in Mail.app.

    I did something similar to what xtravar did.

    I added a view outside the view hierarchy of the tableViewController.

    Then i used the following code in 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
    

    Basically I added the emptyStateView as a subview of the tableView object. As the separators would overlap the view, I set their color to clearColor. To get back to the default separator color, you can just set it to nil.

    0 讨论(0)
  • 2020-12-04 05:56

    Probably not the greatest solution, but I did this by just putting a label at the bottom of my table and if the rows = 0 then I assign it some text. Pretty easy, and achieves what you are trying to do with a few lines of code.

    I have two sections in my table (jobs and schools)

        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 讨论(0)
  • 2020-12-04 05:59

    Using 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
    }
    
    0 讨论(0)
  • 2020-12-04 06:00

    UITableView's backgroundView property is your friend.

    In viewDidLoad or anywhere that you reloadData you should determine if there your table is empty or not and update the UITableView's backgroundView property with a UIView containing a UILabel or just set it to nil. That's it.

    It is of course possible to make UITableView's data source do double duty and return a special "list is empty" cell, it strikes me as a kludge. Suddenly numberOfRowsInSection:(NSInteger)section has to compute the number of rows of other sections it wasn't asked about to make sure they are empty too. You also need to make a special cell that has the empty message. Also don't forget that you need to probably change the height of your cell to accommodate the empty message. This is all doable but it seems like band-aid on top of band-aid.

    0 讨论(0)
提交回复
热议问题