[iphone] 빈 UITableView 처리. 친근한 메시지 인쇄

경우에 따라 비어있는 것이 합법적 인 UITableView가 있습니다. 따라서 앱의 배경 이미지를 표시하는 대신 다음과 같은 친숙한 메시지를 화면에 인쇄하는 것이 좋습니다.

이 목록은 현재 비어 있습니다.

가장 간단한 방법은 무엇입니까?



답변

UITableView의 backgroundView 속성은 친구입니다.

에서 viewDidLoad또는 어디서든 것을 reloadData당신이 당신의 테이블이 비어인지 아닌지 판단하고 UILabel의를 포함하는 UIView의와 jQuery과의 backgroundView의 속성을 업데이트하거나 전무로 설정해야합니다. 그게 다야.

물론 UITableView의 데이터 소스를 이중으로하고 특별한 “list is empty”셀을 반환하는 것이 가능합니다. 갑자기 numberOfRowsInSection:(NSInteger)section비어 있는지 확인하지 않은 다른 섹션의 행 수를 계산해야합니다. 또한 빈 메시지가있는 특수 셀을 만들어야합니다. 또한 빈 메시지를 수용하기 위해 셀의 높이를 변경해야한다는 사실을 잊지 마십시오. 이것은 모두 가능하지만 반창고 위에 반창고처럼 보입니다.


답변

Jhonston의 답변과 동일하지만 확장으로 선호했습니다.

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
}


답변

여기에 대한 답변을 기반으로에서 사용할 수있는 빠른 수업이 있습니다 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/ 의 약간의 도움으로


답변

다음 라이브러리를 권장합니다. DZNEmptyDataSet

프로젝트에 추가하는 가장 쉬운 방법은 다음과 같이 Cocaopods와 함께 사용하는 것입니다. pod 'DZNEmptyDataSet'

TableViewController에서 다음 import 문 (Swift)을 추가합니다.

import DZNEmptyDataSet

그런 다음에 반드시 수업 부합 함을 선언하게 DNZEmptyDataSetSource하고 DZNEmptyDataSetDelegate그래서 같은를 :

class MyTableViewController: UITableViewController, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate

귀하의에서 viewDidLoad다음 코드 줄을 추가합니다 :

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

이제 emptystate를 표시하기 위해해야 ​​할 일은 다음과 같습니다.

//Add title for empty dataset
func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
    let str = "Welcome"
    let attrs = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)]
    return NSAttributedString(string: str, attributes: attrs)
}

//Add description/subtitle on empty dataset
func descriptionForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
    let str = "Tap the button below to add your first grokkleglob."
    let attrs = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleBody)]
    return NSAttributedString(string: str, attributes: attrs)
}

//Add your image
func imageForEmptyDataSet(scrollView: UIScrollView!) -> UIImage! {
    return UIImage(named: "MYIMAGE")
}

//Add your button 
func buttonTitleForEmptyDataSet(scrollView: UIScrollView!, forState state: UIControlState) -> NSAttributedString! {
    let str = "Add Grokkleglob"
    let attrs = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleCallout)]
    return NSAttributedString(string: str, attributes: attrs)
}

//Add action for button
func emptyDataSetDidTapButton(scrollView: UIScrollView!) {
    let ac = UIAlertController(title: "Button tapped!", message: nil, preferredStyle: .Alert)
    ac.addAction(UIAlertAction(title: "Hurray", style: .Default, handler: nil))
    presentViewController(ac, animated: true, completion: nil)
}

이 메소드는 필수가 아니며 버튼 등없이 빈 상태를 표시하는 것도 가능합니다.

Swift 4의 경우

// MARK: - Deal with the empty data set
// Add title for empty dataset
func title(forEmptyDataSet _: UIScrollView!) -> NSAttributedString! {
    let str = "Welcome"
    let attrs = [NSAttributedStringKey.font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.headline)]
    return NSAttributedString(string: str, attributes: attrs)
}

// Add description/subtitle on empty dataset
func description(forEmptyDataSet _: UIScrollView!) -> NSAttributedString! {
    let str = "Tap the button below to add your first grokkleglob."
    let attrs = [NSAttributedStringKey.font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)]
    return NSAttributedString(string: str, attributes: attrs)
}

// Add your image
func image(forEmptyDataSet _: UIScrollView!) -> UIImage! {
    return UIImage(named: "MYIMAGE")
}

// Add your button
func buttonTitle(forEmptyDataSet _: UIScrollView!, for _: UIControlState) -> NSAttributedString! {
    let str = "Add Grokkleglob"
    let attrs = [NSAttributedStringKey.font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.callout), NSAttributedStringKey.foregroundColor: UIColor.white]
    return NSAttributedString(string: str, attributes: attrs)
}

// Add action for button
func emptyDataSetDidTapButton(_: UIScrollView!) {
    let ac = UIAlertController(title: "Button tapped!", message: nil, preferredStyle: .alert)
    ac.addAction(UIAlertAction(title: "Hurray", style: .default, handler: nil))
    present(ac, animated: true, completion: nil)
}


답변

이를 수행하는 한 가지 방법은 1행 수가 0 일 때 반환하도록 데이터 소스를 수정 하고 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적절한 메시지로 구성된 의 인스턴스로 설정하십시오 .


답변

나는 이것을 위해 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;
}


답변

따라서 더 안전한 솔루션을 위해 :

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