Created
November 13, 2025 09:09
-
-
Save dterekhov/d46857f86e3b095274a72a506e1c66f3 to your computer and use it in GitHub Desktop.
UITableView+EmptyData: Placehoder for UITableView on no data state #uikit #swift-api #real-project
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import UIKit | |
| extension UITableView { | |
| // MARK: - Public API | |
| public func fw_setPlaceholder | |
| (text: String?, | |
| fontSize: CGFloat = 21, | |
| image: UIImage?, | |
| edgeInsets: UIEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8)) { | |
| let stackView = fw_placeholderStackView() | |
| if let text = text { | |
| stackView.addArrangedSubview(fw_placeholderLabel(byText: text, fontSize: fontSize)) | |
| } | |
| if let image = image { | |
| stackView.addArrangedSubview(fw_placeholderImageView(byImage: image)) | |
| } | |
| let isPlacehoderEnabled = !stackView.arrangedSubviews.isEmpty // At least one subview | |
| if isPlacehoderEnabled { | |
| let placeholderView = UIView(frame: frame) | |
| placeholderView.backgroundColor = UIColor.green.withAlphaComponent(0.5) | |
| placeholderView.addSubview(stackView) | |
| stackView.centerXAnchor.constraint(equalTo: placeholderView.centerXAnchor).isActive = true | |
| stackView.centerYAnchor.constraint(equalTo: placeholderView.centerYAnchor, | |
| constant: -edgeInsets.top + edgeInsets.bottom).isActive = true | |
| stackView.leadingAnchor.constraint(equalTo: placeholderView.leadingAnchor, | |
| constant: edgeInsets.left).isActive = true | |
| stackView.trailingAnchor.constraint(equalTo: placeholderView.trailingAnchor, | |
| constant: -edgeInsets.right).isActive = true | |
| backgroundView = placeholderView | |
| separatorStyle = .none | |
| } else { | |
| backgroundView = nil | |
| separatorStyle = .singleLine | |
| } | |
| } | |
| // MARK: - Private API | |
| private enum Constants { | |
| static let color = #colorLiteral(red: 0.5607843137, green: 0.5803921569, blue: 0.6117647059, alpha: 1) | |
| } | |
| private func fw_placeholderStackView() -> UIStackView { | |
| let stackView = UIStackView() | |
| stackView.translatesAutoresizingMaskIntoConstraints = false | |
| stackView.axis = .vertical | |
| stackView.alignment = .center | |
| stackView.distribution = .fill | |
| stackView.spacing = 30 | |
| return stackView | |
| } | |
| private func fw_placeholderLabel(byText text: String, fontSize: CGFloat) -> UILabel { | |
| let textAttributes: [NSAttributedString.Key: Any] = | |
| [NSAttributedString.Key.foregroundColor: Constants.color, | |
| NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize)] | |
| // Centering existed attributedString | |
| let style = NSMutableParagraphStyle() | |
| style.alignment = NSTextAlignment.center | |
| let mutableMessage = NSMutableAttributedString(string: text, attributes: textAttributes) | |
| mutableMessage.addAttribute(NSAttributedString.Key.paragraphStyle, | |
| value: style, | |
| range: (mutableMessage.string as NSString) | |
| .range(of: mutableMessage.string)) | |
| let messageLabel = UILabel(frame: CGRect(x: 0, | |
| y: 0, | |
| width: bounds.size.width, | |
| height: bounds.size.height)) | |
| messageLabel.attributedText = mutableMessage | |
| messageLabel.numberOfLines = 0 | |
| messageLabel.sizeToFit() | |
| return messageLabel | |
| } | |
| private func fw_placeholderImageView(byImage image: UIImage) -> UIImageView { | |
| let templateImage = image.withRenderingMode(.alwaysTemplate) | |
| let imageView = UIImageView(image: templateImage) | |
| imageView.tintColor = Constants.color | |
| imageView.translatesAutoresizingMaskIntoConstraints = false | |
| imageView.widthAnchor.constraint(equalToConstant: image.size.width).isActive = true | |
| imageView.heightAnchor.constraint(equalToConstant: image.size.height).isActive = true | |
| return imageView | |
| } | |
| } |
Author
dterekhov
commented
Nov 13, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment