SDWebImageInfo

SDWebImage

簡介

  • iOS中著名的牛逼的網絡圖片處理框架
  • 包含的功能:圖片下載、圖片緩存、下載進度監聽、gif處理等等
  • 用法極其簡單,功能十分強大,大大提高了網絡圖片的處理效率
  • 國內超過90%的iOS項目都有它的影子
  • 框架地址:https://github.com/rs/SDWebImage

獲得框架

  • 進入終端
  • 輸入以下命令
git clone --recursive https://github.com/rs/SDWebImage.git

第三方框架

介紹

  • 由網絡大牛來編寫的框架程序
  • 針對某一個具體的技術問題,提供完善的解決方案

特點

  • 功能強大
  • 有非常好的錯誤處理
  • 持續升級維護

選擇依據

  • 看懂源程序
    • 如果有時間,要儘量閱讀常用框架的源程序並記錄筆記
  • 看人數
  • 看口碑
    • 如果大家都說好,那就大膽的用

使用

  • 工作後,往死裏用
  • 學習中,儘量看懂源程序
  • 獲取框架
  • 導入框架
    • 直接拖拽
      • 編譯,由於絕大多數第三方框架會有對其他框架的依賴,先編譯確認能夠正常使用
    • cocoapod
      • 第三方框架管理工具
      • 終端操作
      • 後面會講

如何學習第三方框架

  • 看官方文檔
  • 運行示例程序,找線索
  • 利用 git 分支添加註釋
  • 編寫測試代碼,整理學習筆記
  • 閱讀源程序(如果是用 C 語言編寫的框架源程序不要看
  • 不要依賴谷歌/百度
    • 因爲第三方框架通常更新的很快,而網絡文章要慢很多
    • 有可能搜索到的一篇文章是很早以前版本的使用文檔

學習第三方框架的好處

  • 瞭解底層實現原理
  • 發現自己的知識空缺點
  • 學習新的實用技術

位移枚舉

  • 位移枚舉是非常古老的 C 語言技巧
  • 按位與 如果都是 1 結果就是1
  • 按位或 如果都是 0 結果就是0

演練

  • 定義枚舉類型
/// 操作類型枚舉
typedef enum {
    ActionTypeTop       = 1 << 0,
    ActionTypeBottom    = 1 << 1,
    ActionTypeLeft      = 1 << 2,
    ActionTypeRight     = 1 << 3
} ActionType;
  • 方法目標

    • 根據操作類型參數,做出不同的響應
    • 操作類型可以任意組合
  • 方法實現

- (void)action:(ActionType)type {

    if (type == 0) {
        NSLog(@"無操作");
        return;
    }

    if (type & ActionTypeTop) {
        NSLog(@"Top %tu", type & ActionTypeTop);
    }
    if (type & ActionTypeBottom) {
        NSLog(@"Bottom %tu", type & ActionTypeBottom);
    }
    if (type & ActionTypeLeft) {
        NSLog(@"Left %tu", type & ActionTypeLeft);
    }
    if (type & ActionTypeRight) {
        NSLog(@"Right %tu", type & ActionTypeRight);
    }
}
  • 方法調用
ActionType type = ActionTypeTop | ActionTypeRight;
[self action:type];

代碼小結

  • 使用 按位或 可以給一個參數同時設置多個 類型
  • 在具體執行時,使用 按位與 可以判斷具體的 類型
  • 通過位移設置,就能夠得到非常多的組合!
  • 對於位移枚舉類型,如果傳入 0,表示什麼附加操作都不做,通常執行效率是最高的
  • 如果開發中,看到位移的枚舉,同時不要做任何的附加操作,參數可以直接輸入 0!

iOS 特有語法

  • iOS 5.0之後,提供了新的枚舉定義方式
  • 定義枚舉的同時,指定枚舉中數據的類型
  • typedef NS_OPTIONS(NSUInteger, NSJSONReadingOptions)
    • 位移枚舉,可以使用 按位或 設置數值
  • typedef NS_ENUM(NSInteger, UITableViewStyle)
    • 數字枚舉,直接使用枚舉設置數值
typedef NS_OPTIONS(NSUInteger, ActionType) {
    ActionTypeTop       = 1 << 0,
    ActionTypeBottom    = 1 << 1,
    ActionTypeLeft      = 1 << 2,
    ActionTypeRight     = 1 << 3
};

NSCache

介紹

  • NSCache 是蘋果提供的一個專門用來做緩存的類
  • 使用和 NSMutableDictionary 非常相似
  • 是線程安全的
  • 當內存不足的時候,會自動清理緩存
  • 程序開始時,可以指定緩存的數量 & 成本

方法

  • 取值

    • - (id)objectForKey:(id)key;
  • 設置對象,0成本

    • - (void)setObject:(id)obj forKey:(id)key;
  • 設置對象並指定成本

    • - (void)setObject:(id)obj forKey:(id)key cost:(NSUInteger)g;
  • 成本示例,以圖片爲例:

    • 方案一:緩存 100 張圖片
    • 方案二:總緩存成本設定爲 10M,以圖片的 寬 * 高當作成本,圖像像素。這樣,無論緩存的多少張照片,只要像素值超過 10M,就會自動清理
    • 結論:在緩存圖像時,使用成本,比單純設置數量要科學!
  • 刪除

    • - (void)removeObjectForKey:(id)key;
  • 刪除全部(不要使用!)

    • - (void)removeAllObjects;

屬性

  • @property NSUInteger totalCostLimit;

    • 緩存總成本
  • @property NSUInteger countLimit;

    • 緩存總數量
  • @property BOOL evictsObjectsWithDiscardedContent;

    • 是否自動清理緩存,默認是 YES

代碼演練

  • 定義緩存屬性
@property (nonatomic, strong) NSCache *cache;
  • 懶加載並設置限制
- (NSCache *)cache {
    if (_cache == nil) {
        _cache = [[NSCache alloc] init];
        _cache.delegate = self;
        _cache.countLimit = 10;
    }
    return _cache;
}
  • 觸摸事件添加緩存
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    for (int i = 0; i < 20; ++i) {
        NSString *str = [NSString stringWithFormat:@"%d", i];
        NSLog(@"set -> %@", str);
        [self.cache setObject:str forKey:@(i)];
        NSLog(@"set -> %@ over", str);
    }

    // 遍歷緩存
    NSLog(@"------");

    for (int i = 0; i < 20; ++i) {
        NSLog(@"%@", [self.cache objectForKey:@(i)]);
    }
}

// 代理方法,僅供觀察使用,開發時不建議重寫此方法
- (void)cache:(NSCache *)cache willEvictObject:(id)obj {
    NSLog(@"remove -> %@", obj);
}

修改網絡圖片框架

  • 修改圖像緩衝池類型,並移動到 .h 中,以便後續測試
///  圖像緩衝池
@property (nonatomic, strong) NSCache *imageCache;
  • 修改懶加載,並設置數量限制
- (NSCache *)imageCache {
    if (_imageCache == nil) {
        _imageCache = [[NSCache alloc] init];
        _imageCache.countLimit = 15;
    }
    return _imageCache;
}
  • 修改其他幾處代碼,將 self.imageCache[URLString] 替換爲 [self.imageCache setObject:image forKey:URLString];

  • 測試緩存中的圖片變化

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    for (AppInfo *app in self.appList) {
        NSLog(@"%@ %@", [[DownloadImageManager sharedManager].imageCache objectForKey:app.icon], app.name);
    }
}
  • 註冊通知,監聽內存警告
- (instancetype)init
{
    self = [super init];
    if (self) {
        // 註冊通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clearMemory) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
    }
    return self;
}

// 提示:雖然執行不到,但是寫了也無所謂
- (void)dealloc {
    // 刪除通知
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
  • 清理內存
- (void)clearMemory {
    NSLog(@"%s", __FUNCTION__);

    // 取消所有下載操作
    [self.downloadQueue cancelAllOperations];

    // 刪除緩衝池
    [self.operationChache removeAllObjects];
}

注意:內存警告或者超出限制後,緩存中的任何對象,都有可能被清理。使用 NSCache 做緩存一定要保證能夠有恢復的通道!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章