你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 零行代碼為App添加異常加載占位圖

零行代碼為App添加異常加載占位圖

編輯:IOS開發基礎

32.png

本文為投稿文章,作者:賣報的小畫家Sure  原文


前文提要

近期准備重構項目,需要重寫一些通用模塊,正巧需要設置App異常加載占位圖的問題,心血來潮設想是否可以零行代碼解決此問題,特在此分享實現思路。

思路分享

對於App占位圖,通常需要考慮的控件有tableView、collectionView和webView,異常加載情況區分為無數據和網絡異常等。

既然要實現零代碼形式,因此就不能繼承原始類重寫或添加方法等方式,而是通過對對應控件添加類別(分類)來實現。

簡單來說,以tableView為例實現思路為每當tableView調用reloadData進行刷新時,檢測此時tableView行數,若行數不為零,正常顯示數據。若行數為零,說明無數據顯示占位圖。

添加占位圖的方式有很多種,例如借助tableView的backgroundView或直接以addSubView的方式添加,這裡采用的為addSubView方式,盡量避免原生屬性的占用。

對於檢測tableView數據是否為空,借助tableView的代理dataSource即可。核心代碼如下,依次獲取tableView所具有的組數與行數,通過isEmpty這個flag標示最後確定是否添加占位圖。

- (void)checkEmpty {
    BOOL isEmpty = YES;//flag標示

    id  dataSource = self.dataSource;
    NSInteger sections = 1;//默認一組
    if ([dataSource respondsToSelector:@selector(numberOfSectionsInTableView:)]) {
        sections = [dataSource numberOfSectionsInTableView:self] - 1;//獲取當前TableView組數
    }

    for (NSInteger i = 0; i <= sections; i++) {
        NSInteger rows = [dataSource tableView:self numberOfRowsInSection:sections];//獲取當前TableView各組行數
        if (rows) {
            isEmpty = NO;//若行數存在,不為空
        }
    }
    if (isEmpty) {//若為空,加載占位圖
        if (!self.placeholderView) {//若未自定義,展示默認占位圖
            [self makeDefaultPlaceholderView];
        }
        self.placeholderView.hidden = NO;
        [self addSubview:self.placeholderView];
    } else {//不為空,隱藏占位圖
        self.placeholderView.hidden = YES;
    }
}

相應的對於CollectionView亦可通過numberOfSectionsInCollectionView:和collectionView:numberOfItemsInSection獲取其組數和行數,這裡就不一一贅述。

需要注意的為webView占位圖是否顯示的判斷,一種情況為webView調用其webView: didFailLoadWithError:方法,第二種為webView完成加載顯示為空的情況。但存在的一個問題是,webView沒有必選的協議方法,或可能根本沒有設置代理。因此無法很好的判斷webView是否響應其協議方法。因此該demo暫時沒有添加webView的占位圖,如果有好的想法可以評論指出。

接下來說最重要的一步,如何實現零行代碼添加占位圖呢?

其實實現思路非常簡單,如果可以讓tableView在執行reloadData時自動檢測其行數就可以了。也就是我們需要在reloadData原有方法的基礎上添加checkEmpty此方法。

這裡又能體現到Runtime Method Swizzling的作用了,我們可以通過Method Swizzling替換reloadData方法,給予它新的實現。核心代碼如下:

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //方法交換,將reloadData實現交換為sure_reloadData
        [self methodSwizzlingWithOriginalSelector:@selector(reloadData) bySwizzledSelector:@selector(sure_reloadData)];
    });
}

- (void)sure_reloadData {
    [self checkEmpty];
    [self sure_reloadData];
}

這樣就可以實現reloadData的同時檢測行數從而判斷是否顯示占位圖的功能。
這裡采用了上篇文章《Runtime Method Swizzling開發實例匯總》的代碼用例類NSObject+Swizzling.h,因此該篇文章也算上篇文章的延續,為Runtime Method Swizzling的另一種用例。感興趣的朋友可以前往閱讀更多的實用用例。

為實現零代碼的效果,代碼中已添加了placeholder視圖的默認樣式,如圖所示:

1767950-359ca5b4d9ce8452.png

占位圖樣式

若要實現效果圖中點擊圖標重新刷新效果,需要讓tableView調用reloadBlock,因為數據的刷新大多是不同的,所以具體刷新執行代碼還是需要自己手動設置的。若不需要,則無需添加此操作。

[_tableView setReloadBlock:^{
      //刷新操作
}];

如果需要自定制占位視圖樣式也非常簡單,因占位圖樣式比較統一,所以可直接修改SurePlaceholderView占位圖類以達到自己想要的效果,再而在UITableView+Sure_Placeholder.h、UICollectionView+Sure_Placeholder.h、UIWebView+Sure_Placeholder.h類別中均外漏了placeholderView屬性,將其賦值為新的視圖亦可。

以tableView為例,可以通過如下方式進行修改

_tableView.placeholderView =[[CustomPlaceholderView alloc]initWithFrame:_tableView.bounds];

同樣的對於無數據與無網絡的效果切換,也可以通過網絡是否可用的標示來進行展示不同的占位圖。例如

if (is_Net_Available) {
   _tableView.placeholderView = [[CustomPlaceholderView alloc]initWithFrame:_tableView.bounds];
 } else {
   _tableView.placeholderView = [[NetNoAvailableView alloc]initWithFrame:_tableView.bounds];
}

為方便大家閱讀和修改,demo已上傳github。

下載鏈接如下:零行代碼為App添加無數據占位圖????

既然為零代碼,因此使用方法將Sure_Placeholder文件夾拖入工程即可。有任何問題大家可以評論指出。

參考鏈接:《一行代碼完成“空TableView占位視圖”管理》

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved