Swift 空資料介面顯示模組封裝實現
一個Swift語言封裝的EmptyView顯示庫,可作用於WKWebView、UITableView、UICollectionView
示例
-
WKWebView
-
UITableView
- UICollectionView
引言:
專案開發過程中當網路斷開或者資料獲取失敗導致的介面顯示為空的情況下,我們常會用到圖片加文字加重新整理按鈕、文字加重新整理按鈕或者純文字提醒的空介面顯示,所以對該功能實現的封裝封裝就顯得很有必要。
該技術封裝模組使用Swift語言,參考OC封裝模組的內部實現邏輯,利用runtime的系統方法交換機制,實現在WKWebView網頁載入介面、UITableView、UICollectionView列表檢視等介面資料獲取失敗情況下的提醒顯示和重新整理操作功能。
一:內部實現原理
1、通過runtime key值關聯HDEmptyView顯示物件
建立UIScrollView的extension物件UIScrollView+Empty類,通過runtime key值關聯HDEmptyView顯示介面物件ly_emptyView ,該物件可根據呼叫介面的引數設定來控制空介面顯示的內容、佈局樣式、顏色等。
struct RuntimeKey {
static let kEmptyViewKey = UnsafeRawPointer.init(bitPattern: "kEmptyViewKey".hashValue)
}
public var ly_emptyView: HDEmptyView? {
set {
objc_setAssociatedObject(self, RuntimeKey.kEmptyViewKey!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
for view in self.subviews {
if view.isKind(of: HDEmptyView.classForCoder()) {
view.removeFromSuperview()
}
}
self.addSubview(ly_emptyView!)
self.ly_emptyView?.isHidden = true
}
get {
return objc_getAssociatedObject(self, RuntimeKey.kEmptyViewKey!) as? HDEmptyView
}
}
2、WKWebView 呼叫顯隱方法
如果是WKWebView的空資料介面顯示,根據介面載入成功或失敗的情況,呼叫顯示/隱藏空介面方法
public func ly_showEmptyView() {
self.ly_emptyView?.superview?.layoutSubviews()
self.ly_emptyView?.isHidden = false
//始終保持顯示在最上層
if self.ly_emptyView != nil {
self.bringSubview(toFront: self.ly_emptyView!)
}
}
public func ly_hideEmptyView() {
self.ly_emptyView?.isHidden = true
}
3、列表檢視顯隱控制
如果是UITableView、UICollectionView則根據DataSource判斷是否自動顯示emptyView
首先獲取當前列表檢視上cell的個數
//MARK: - Private Method
fileprivate func totalDataCount() -> NSInteger {
var totalCount: NSInteger = 0
if self.isKind(of: UITableView.classForCoder()) {
let tableView = self as? UITableView
if (tableView?.numberOfSections)! >= 1 {
for section in 0...(tableView?.numberOfSections)!-1 {
totalCount += (tableView?.numberOfRows(inSection: section))!
}
}
}
else if self.isKind(of: UICollectionView.classForCoder()) {
let collectionView = self as? UICollectionView
if (collectionView?.numberOfSections)! >= 1 {
for section in 0...(collectionView?.numberOfSections)!-1 {
totalCount += (collectionView?.numberOfItems(inSection: section))!
}
}
}
return totalCount
}
然後根據cell的個數判斷是否顯示 emptyView
fileprivate func getDataAndSet() {
if self.totalDataCount() == 0 {
show()
} else {
hide()
}
}
fileprivate func show() {
if self.ly_emptyView?.autoShowEmptyView == false {
self.ly_emptyView?.isHidden = true
return
}
ly_showEmptyView()
}
fileprivate func hide() {
if self.ly_emptyView?.autoShowEmptyView == false {
self.ly_emptyView?.isHidden = true
return
}
ly_hideEmptyView()
}
4、列表檢視的方法交換與介面重新整理顯示
private static let swizzleMethod: Void = {
//insertSections
let originalSelector = #selector(insertSections(_:with:))
let swizzledSelector = #selector(ly_insertSections(_:with:))
HDRunTime.exchangeMethod(selector: originalSelector, replace: swizzledSelector, class: UITableView.self)
//deleteSections
let originalSelector1 = #selector(deleteSections(_:with:))
let swizzledSelector1 = #selector(ly_deleteSections(_:with:))
HDRunTime.exchangeMethod(selector: originalSelector1, replace: swizzledSelector1, class: UITableView.self)
//insertRows
let originalSelector2 = #selector(insertRows(at:with:))
let swizzledSelector2 = #selector(ly_insertRowsAtIndexPaths(at:with:))
HDRunTime.exchangeMethod(selector: originalSelector2, replace: swizzledSelector2, class: UITableView.self)
//deleteRows
let originalSelector3 = #selector(deleteRows(at:with:))
let swizzledSelector3 = #selector(ly_deleteRowsAtIndexPaths(at:with:))
HDRunTime.exchangeMethod(selector: originalSelector3, replace: swizzledSelector3, class: UITableView.self)
//reload
let originalSelector4 = #selector(reloadData)
let swizzledSelector4 = #selector(ly_reloadData)
HDRunTime.exchangeMethod(selector: originalSelector4, replace: swizzledSelector4, class: UITableView.self)
}()
//section
@objc func ly_insertSections(_ sections: NSIndexSet, with animation: UITableViewRowAnimation) {
ly_insertSections(sections, with: animation)
getDataAndSet()
}
@objc func ly_deleteSections(_ sections: NSIndexSet, with animation: UITableViewRowAnimation) {
ly_deleteSections(sections, with: animation)
getDataAndSet()
}
//row
@objc func ly_insertRowsAtIndexPaths(at indexPaths: [IndexPath], with animation: UITableViewRowAnimation){
ly_insertRowsAtIndexPaths(at: indexPaths, with: animation)
getDataAndSet()
}
@objc func ly_deleteRowsAtIndexPaths(at indexPaths: [IndexPath], with animation: UITableViewRowAnimation){
ly_deleteRowsAtIndexPaths(at: indexPaths, with: animation)
getDataAndSet()
}
//reloadData
@objc func ly_reloadData() {
self.ly_reloadData()
self.getDataAndSet()
}
二:使用方法
1、建立 HDEmptyView 介面顯示物件
//建立方式一:Block回撥
let emptyV:HDEmptyView = HDEmptyView.emptyActionViewWithImageStr(imageStr: "net_error_tip", titleStr: "暫無資料,點選重新載入", detailStr: "", btnTitleStr: "點選重新整理") {
print("點選重新整理")
weakSelf?.reloadDataWithCount(count: 4)
}
//建立方式二:target/action
let emptyV:HDEmptyView = HDEmptyView.emptyActionViewWithImageStr(imageStr: "net_error_tip", titleStr: "暫無資料,點選重新載入", detailStr: "", btnTitleStr: "點選重新整理", target: self, action: #selector(reloadBtnAction)) as! HDEmptyView
2、設定顯示引數屬性
emptyV.titleLabTextColor = UIColor.red
emptyV.actionBtnFont = UIFont.systemFont(ofSize: 19)
emptyV.contentViewOffset = -50
emptyV.actionBtnBackGroundColor = .white
emptyV.actionBtnBorderWidth = 0.7
emptyV.actionBtnBorderColor = UIColor.gray
emptyV.actionBtnCornerRadius = 10
3、賦值給當前顯示物件的ly_emptyView
webView.scrollView.ly_emptyView = emptyV
tableView.ly_emptyView = emptyV
collectionView.ly_emptyView = emptyV
//設定點選空白區域是否有重新整理操作
self.webView.scrollView.ly_emptyView?.tapContentViewBlock = {
//weakSelf!.loadingURL(urltring: "http://news.baidu.com/")
}
4、自定義空資料介面顯示
//自定義空資料介面顯示
func setupMyEmptyView() {
let emptyView: MyEmptyView = Bundle.main.loadNibNamed("MyEmptyView", owner: self, options: nil)?.last as! MyEmptyView
emptyView.reloadBtn.addTarget(self, action: #selector(reloadBtnAction(_:)), for: UIControlEvents.touchUpInside)
emptyView.frame = view.bounds
//空資料介面顯示
let emptyV:HDEmptyView = HDEmptyView.emptyViewWithCustomView(customView: emptyView) as! HDEmptyView
tableView.ly_emptyView = emptyV
tableView.ly_emptyView?.tapContentViewBlock = {
print("點選介面空白區域")
}
tableView.ly_showEmptyView()
}
注意事項:
是否自動顯隱EmptyView的引數 autoShowEmptyView 預設設定是true,列表檢視會根據介面cell的count數量自動顯隱空介面。
當設定成false時只能手動呼叫 ly_showEmptyView() 和 ly_hideEmptyView() 方法進行顯隱操作
相關文章
- iOS資料上報模組封裝方案iOS封裝
- 封裝模組實現商品增刪改查封裝
- java web實現分頁顯示資料JavaWeb
- 關於逐步顯示資料如何實現
- 價格顯示檢視封裝封裝
- 封裝一個 Swift-Style 的網路模組封裝Swift
- 程式介面多模式顯示的實現 (轉)模式
- 基於IIC介面的OLED資料顯示
- java 資料結構實現陣列封裝 (一)Java資料結構陣列封裝
- Swift - Alamofire與Cache封裝實現網路快取、下載Swift封裝快取
- 基於SPI/IIC介面的OLED資料顯示
- 封裝介面封裝
- JavaScript 模組封裝JavaScript封裝
- QT介面顯示實時時間QT
- 介面的實現方式(顯示和隱示)及協變和逆變
- 介面自動化之實現日誌記錄封裝封裝
- C++庫封裝JNI介面——實現java呼叫c++C++封裝Java
- java實現將資料庫資料轉化成excel表格顯示出來Java資料庫Excel
- Swift TextView Placeholder封裝SwiftTextView封裝
- MyFaces整合sitemesh,以及使用MyFaces實現資料分頁顯示
- 利用ASP實現Oracle資料記錄的分頁顯示Oracle
- MyEclipse顯示中文介面,線上安裝教程Eclipse
- C++ 使用 hiredis 封裝redis 的資料獲取介面C++Redis封裝
- Vue — 請求模組、api模組封裝VueAPI封裝
- Geoserver + MySQL實現圖層顯示和文字顯示ServerMySql
- CSS實現限制顯示的字數,超出顯示"..."CSS
- Highcharts結合後臺實現圖餅資料顯示
- 實現分頁顯示資料[並按關鍵字查詢]
- Swift keychain 官方封裝DemoSwiftAI封裝
- [hyperf]關於資料返回封裝的另一種實現思考封裝
- jive 安裝上了,可是中文介面不能正常顯示。
- 基於STM32的OLED的SPI介面資料顯示
- asp.net mvc 中利用jquery datatables 實現資料分頁顯示ASP.NETMVCjQuery
- element table不顯示任何資料,無資料倒是顯示出無資料的了
- 淘寶商品評論資料介面,電商平臺評論介面,行業商品評論資料介面程式碼封裝教程行業封裝
- WireShark資料包分析資料封裝封裝
- 詳細顯示資料表空間的使用率與剩餘空間的SQLSQL
- 微信域名防封API介面實現原理分享API