Swift5.0 扩展 UITableView 实现全局空白视图

102 阅读1分钟
//
//  UITableViewTempDataExtensions.swift
//  TeaCrap
//
//  Created by Cee on 2023/3/14.
//  Copyright © 2023 rs. All rights reserved.
//

import UIKit

extension UITableView {
    
    static var kTempViewEnableKey =  0x2023031509
    static let kTempViewTag: Int = 0x2023031510
    
    /// 返回 UItableview 条数
    func numberOfRows() -> Int {
        var section = 0
        var rowCount = 0
        while section < numberOfSections {
            rowCount += numberOfRows(inSection: section)
            section += 1
        }
        return rowCount
    }
    
    /// 是否启用 空白视图
    var mEnableTempView: Bool {
        get {
            let enable = objc_getAssociatedObject(self, &UITableView.kTempViewEnableKey) as? Bool
            return enable ?? true
        }
        set {
            objc_setAssociatedObject(self, &UITableView.kTempViewEnableKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    /// 空白视图
    var mTempView: TableViewBlankView {
        get {
            let targetView = subviews.first(where: { $0.tag == UITableView.kTempViewTag })
            if let tempView = targetView as? TableViewBlankView {
                return tempView
            } else {
                let tempView = TableViewBlankView(frame: .zero) { [weak self] in
                    self?.mj_header?.beginRefreshing()
                }
                tempView.tag = UITableView.kTempViewTag
                addSubview(tempView)
                tempView.snp.remakeConstraints { make in
                    make.center.equalToSuperview()
                    make.width.equalToSuperview()
                    make.height.equalTo(220)
                }
                return tempView
            }
        }
    }
    
    /// 方法交换 设置默认空白视图
    class func cy_load() {
        let originalSelector = #selector(UITableView.reloadData as (UITableView) -> () -> Void)
        let swizzledSelector = #selector(UITableView.cy_reloadData as (UITableView) -> () -> Void)

        let _originalMethod = class_getInstanceMethod(self, originalSelector)
        let _swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
        
        guard let originalMethod = _originalMethod, let swizzledMethod = _swizzledMethod else { return }

        let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
        if didAddMethod {
            class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    }
    
    /// 更新空白视图
    func updateBlankView(with
                         title: String,
                         image: String?=nil,
                         font: UIFont=UIFont.systemFont(ofSize: 15),
                         color: UIColor=UIColor.black ){
        if let imgName = image {
            mTempView.mTempImageView.image = UIImage(named: imgName)
        }
        mTempView.mTempLabel.setAttributedTitle(title.font(font).color(color), for: .normal)
    }
    
    /// 刷新数据
    @objc func cy_reloadData() {
        cy_reloadData()
        if mEnableTempView {
            let rows = numberOfRows()
            mTempView.isHidden = rows != 0
        }
        else {
            mTempView.isHidden = true
        }
    }
}


class TableViewBlankView: UIView {
    
    private var mReloadTap: VoidClosure?
    
    lazy var mTempLabel: UIButton = {
        let label = UIButton()
        let color = UIColor.gray.withAlphaComponent(0.7)
        let font = UIFont.systemFont(ofSize: 15)
        label.setTitle("暂无数据", for: .normal)
        label.titleLabel?.font = .systemFont(ofSize: 15)
        label.titleLabel?.numberOfLines = 0
        label.titleLabel?.textAlignment = .center
        label.setTitleColor(.black.withAlphaComponent(0.4), for: .normal)
        label.addTarget(self, action: #selector(onTempLabelTap), for: .touchUpInside)
        return label
    }()
    
    lazy var mTempImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.isUserInteractionEnabled = true
        imageView.image = UIImage(named: "img_NoData")
        imageView.contentMode = .scaleToFill
        return imageView
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        addSubview(mTempImageView)
        mTempImageView.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.width.equalTo(220)
            make.height.equalTo(220)
        }
        
        mTempImageView.addSubview(mTempLabel)
        mTempLabel.snp.makeConstraints { make in
            make.center.equalToSuperview()
        }
    }
    
    convenience init(frame: CGRect, onTap: @escaping VoidClosure) {
        self.init(frame: frame)
        self.mReloadTap = onTap
    }
    
    @objc func onTempLabelTap() {
        mReloadTap?()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

/// 空白回调
typealias VoidClosure = () -> Void

// MARK: - Attributed String
extension String {
    var attributed: NSMutableAttributedString {
        get {
            return NSMutableAttributedString(string: self)
        }
    }
    func color(_ color: UIColor) -> NSMutableAttributedString {
        return attributed.color(color)
    }
    func font(_ font: UIFont) -> NSMutableAttributedString {
        return attributed.font(font)
    }
    func size(_ size: CGFloat) -> NSMutableAttributedString {
        return attributed.size(size)
    }
}

extension NSMutableAttributedString {
    func color(_ color: UIColor) -> NSMutableAttributedString {
        addAttributes([.foregroundColor:color], range: NSRange(location: 0, length: string.count))
        return self
    }
    func font(_ font: UIFont) -> NSMutableAttributedString {
        addAttributes([.font: font], range: NSRange(location: 0, length: string.count))
        return self
    }
    func size(_ size: CGFloat) -> NSMutableAttributedString {
        addAttributes([.font: UIFont.systemFont(ofSize: size)], range: NSRange(location: 0, length: string.count))
        return self
    }
}