[Swift]添加暂无数据和暂无网络缺省页

2024-08-20 22:32

本文主要是介绍[Swift]添加暂无数据和暂无网络缺省页,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Demo
GitHub
每个项目都会对暂无数据和暂无网络进行处理, 提前将这些功能提取出来, 便于以后使用方便.
先pods导入第三方框架,然后拓展控制器的基类.

  pod 'EmptyDataSet-Swift', '5.0.0'# 网络监测pod 'ReachabilitySwift'

最后使用时用一句代码解决:

setupEmptyData(scrollView: tableView, reload: true, image: UIImage(named: "icon_qs_data.png"))

示意图:
在这里插入图片描述
[代码备份]
下面是模拟的一个列表:

import Foundation
import UIKit
import MJRefreshclass GAHomeVC: BaseVC {@IBOutlet weak var tableView: UITableView!var listArr: [[String: String]] = []var page: Int = 1override func viewDidLoad() {super.viewDidLoad()setupUI()anewReloadData()}func setupUI() {tableView.separatorStyle = .noneadjustsScrollViewInsetNever(scrollView: tableView)setupScrollReload()}override func anewReloadData() {super.anewReloadData()page = 1requestListData()}func setupScrollReload() {let mjheader = MJRefreshNormalHeader { [weak self] inself?.anewReloadData()}mjheader.stateLabel?.textColor = .blackmjheader.lastUpdatedTimeLabel?.isHidden = truetableView.mj_header = mjheaderanewReloadData()let footer = MJRefreshAutoNormalFooter { [weak self] inself?.page += 1self?.requestListData()}footer.isHidden = truefooter.setTitle("暂无更多数据", for: .noMoreData)footer.stateLabel?.textColor = #colorLiteral(red: 0.6, green: 0.6, blue: 0.6, alpha: 0.5)tableView.mj_footer = footer}@IBAction func tapEmptyAction(_ sender: Any) {tableView.mj_footer?.isHidden = truelistArr.removeAll()page = -1requestListData()}}extension GAHomeVC {func requestListData() {if page == 1 {listArr.removeAll()}let data = moniData()listArr += dataendRefreshing()if data.count < 20 {tableView.mj_footer?.endRefreshingWithNoMoreData()} else {tableView.mj_footer?.resetNoMoreData()}if listArr.count < 20 {tableView.mj_footer?.isHidden = true} else {tableView.mj_footer?.isHidden = false}tableView.reloadData()setupEmptyData(scrollView: tableView, reload: true, image: UIImage(named: "icon_qs_data.png"), space: -70)}func endRefreshing() {if let header = tableView.mj_header , header.isRefreshing {header.endRefreshing()}if let footer = tableView.mj_footer , footer.isRefreshing {footer.endRefreshing()}}func moniData() -> [[String: String]] {if !NetstatManager.shared.isNetworkConnect() {return []}var listCount = 0if page == 1 {listCount = 20} else if page == 2 {listCount = 10} else {return []}var tempArr: [[String: String]] = []for index in ((page-1)*20)..<((page-1)*20+listCount) {let obj = ["title": "title\(index)", "id": "\(index)"]tempArr.append(obj)}return tempArr}}extension GAHomeVC: UITableViewDelegate, UITableViewDataSource {func numberOfSections(in tableView: UITableView) -> Int {return 1}func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {return listArr.count}func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {let cell = UITableViewCell(style: .default, reuseIdentifier: "UITableViewCell")cell.selectionStyle = .noneif listArr.count > indexPath.row {let obj = listArr[indexPath.row]cell.textLabel?.text = obj["title"]}return cell}func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {}}

对BaseVC进行功能扩展:

import UIKit
import EmptyDataSet_Swift
import SnapKitclass BaseVC: UIViewController {// 暂无数据 自定义视图var emptyDataCustomView: EmptyDataCustomView?// 暂无网络 自定义视图lazy var netAlert: NetstatAlertVC = {let alert = NetstatAlertVC()alert.modalPresentationStyle = .overCurrentContextalert.modalTransitionStyle = .coverVerticalalert.tranferReloadBlock { [weak self] result inself?.anewReloadData()}return alert}()deinit {NotificationCenter.default.removeObserver(self, name: Notification.Name("NetworkStatusChange"), object: nil)}override func viewDidLoad() {super.viewDidLoad()view.backgroundColor = .systemGray5if #available(iOS 13.0, *) {overrideUserInterfaceStyle = .light} else {// Fallback on earlier versions}}override func viewWillAppear(_ animated: Bool) {super.viewWillAppear(animated)}// MARK: iOS11设置 使用安全区域func adjustsScrollViewInsetNever(scrollView:UIScrollView) {if #available(iOS 11.0, *){scrollView.contentInsetAdjustmentBehavior = .never}else{self.automaticallyAdjustsScrollViewInsets = false}}// MARK: 重新加载刷新数据@objc func anewReloadData() {}}// MARK: 暂无数据/暂无网络
extension BaseVC {/**@abstract 处理暂无数据@param scrollView: 容器@param reload: 是否有刷新按钮@param alert: 提示文字@param image: 提示图片@param space: 文字顶部距离图片底部的相对偏移@param mark: 0表示Size15 #333333, 1表示Size13 #999999@param onlyNet: 方法中只处理暂无网络的提示*/func setupEmptyData(scrollView: UIScrollView?,reload: Bool = false,alert: String = "暂无数据",image: UIImage? = nil,space: CGFloat = 0,mark: Int = 0,onlyNet: Bool = false) {if !NetstatManager.shared.isNetworkConnect() {noNetstatAction(scrollView)return}if onlyNet {return}guard let scr = scrollView else {return}scr.emptyDataSetView { [weak self] view inif self?.emptyDataCustomView == nil {let customView = Bundle.main.loadNibNamed("EmptyDataCustomView", owner: nil, options: nil)![0] as! EmptyDataCustomViewcustomView.setupAlertData(image: image, msg: alert, space: space, mark: mark)if reload {customView.tranferParameterClosure { [weak self] result inself?.anewReloadData()}}self?.emptyDataCustomView = customView}view.customView(self?.emptyDataCustomView).verticalOffset(-50)}}/**@abstract 处理暂无网络@param haveData: 是否有数据@param reload: 是否有刷新按钮*/private func noNetstatAction(_ scrollView: UIScrollView?) {var haveData = falseif let tv = scrollView as? UITableView {let cells = tv.visibleCellsif cells.count > 0 {haveData = true}} else if let co = scrollView as? UICollectionView {let cells = co.visibleCellsif cells.count > 0 {haveData = true}}if !NetstatManager.shared.isNetworkConnect() && haveData == false {NotificationCenter.default.addObserver(self, selector: #selector(networkStatusChange(_:)), name: Notification.Name("NetworkStatusChange"), object: nil)self.view.addSubview(netAlert.view)self.view.bringSubviewToFront(netAlert.view)let top: CGFloat = UIApplication.shared.statusBarFrame.height + 44netAlert.view.snp.remakeConstraints { make inmake.bottom.left.right.equalToSuperview()make.top.equalToSuperview().offset(top)}} else {netAlert.view.removeFromSuperview()}}/// 网络状态从无网络切换到有网络时,通知刷新@objc func networkStatusChange(_ sender: Notification) {noNetstatAction(nil)if let topVC = ScreenUIManager.topViewController() {if topVC.theClassName == self.theClassName {anewReloadData()}}NotificationCenter.default.removeObserver(self, name: Notification.Name("NetworkStatusChange"), object: nil)}}extension NSObject {// 获取对象的类名var theClassName: String {return NSStringFromClass(type(of: self))}
}

暂无数据时的提示视图:

import Foundation
import UIKitclass EmptyDataCustomView: UIView {@IBOutlet weak var alertIV: UIImageView!@IBOutlet weak var ivHConstraint: NSLayoutConstraint!@IBOutlet weak var alertLab: UILabel!@IBOutlet weak var reloadBut: UIButton!@IBOutlet weak var devConstraint: NSLayoutConstraint!private var reloadBlock:((String) -> Void)?override func layoutSubviews() {super.layoutSubviews()}override func awakeFromNib() {super.awakeFromNib()}@IBAction func tapRloadAction(_ sender: Any) {if self.reloadBlock != nil {self.reloadBlock!("刷新了")}}public func tranferParameterClosure(callbackEnclosure:@escaping ((String) -> Void)) {self.reloadBlock = callbackEnclosurereloadBut.isHidden = false}func setupAlertData(image:UIImage?, msg:String, space:CGFloat, mark:Int) {alertIV.image = imagealertLab.text = msgdevConstraint.constant = spaceif mark == 1 {alertLab.textColor = .darkGrayalertLab.font = UIFont.systemFont(ofSize: 13)} else {alertLab.textColor = .blackalertLab.font = UIFont.boldSystemFont(ofSize: 15)}var viewHeight: CGFloat = 100if let ig = image {let igSize = ig.size // 默认都是传的二倍图let newIgSize = CGSize(width: igSize.width/2.0, height: igSize.height/2.0)ivHConstraint.constant = newIgSize.heightviewHeight = viewHeight+newIgSize.height} else {ivHConstraint.constant = 0.0}self.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width - 40, height: viewHeight)}}

网络管理:

import Foundation
import Reachabilityclass NetstatManager: UIViewController {/// 单例static let shared = NetstatManager()/// Reachability必须一直存在,所以需要设置为全局变量let reachability = try! Reachability()lazy var netAlert: NetstatAlertVC = {let alert = NetstatAlertVC()alert.modalPresentationStyle = .overCurrentContextalert.modalTransitionStyle = .coverVerticalreturn alert}()deinit {// 关闭网络状态消息监听reachability.stopNotifier()// 移除网络状态消息通知NotificationCenter.default.removeObserver(self, name: Notification.Name.reachabilityChanged, object: reachability)}override func viewDidLoad() {super.viewDidLoad()}/// 判断是否联网func isNetworkConnect() -> Bool {return reachability.isReachable}}extension NetstatManager {/// 网络状态监听func NetworkStatusListener() {// 1、设置网络状态消息监听 2、获得网络Reachability对象NotificationCenter.default.addObserver(self, selector: #selector(self.reachabilityChanged),name: Notification.Name.reachabilityChanged,object: reachability)do {// 3、开启网络状态消息监听try reachability.startNotifier()} catch {print("could not start reachability notifier")}}/// 主动监测网络状态@objc func reachabilityChanged(note: NSNotification) {let reachability = note.object as! Reachabilityif reachability.isReachable {if reachability.isReachableViaWiFi {print("连接类型:WiFi")} else {print("连接类型:移动网络")}self.netAlert.dismiss(animated: false, completion: nil)// 由无网络到有网络时才发出通知NotificationCenter.default.post(name: NSNotification.Name("NetworkStatusChange"), object: nil)} else {print("连接类型:暂无网络")self.alert_noNetwrok()}}/// 警告框,提示没有连接网络func alert_noNetwrok() -> Void {if let topVC = ScreenUIManager.topViewController() {if let _ = topVC as? NetstatAlertVC {return}}// UIApplication.shared.keyWindow?.rootViewController?.present(self.netAlert, animated: false, completion: nil)}}

这篇关于[Swift]添加暂无数据和暂无网络缺省页的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1091351

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

烟火目标检测数据集 7800张 烟火检测 带标注 voc yolo

一个包含7800张带标注图像的数据集,专门用于烟火目标检测,是一个非常有价值的资源,尤其对于那些致力于公共安全、事件管理和烟花表演监控等领域的人士而言。下面是对此数据集的一个详细介绍: 数据集名称:烟火目标检测数据集 数据集规模: 图片数量:7800张类别:主要包含烟火类目标,可能还包括其他相关类别,如烟火发射装置、背景等。格式:图像文件通常为JPEG或PNG格式;标注文件可能为X

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依