SDWebImage
簡介
- iOS中著名的牛逼的網絡圖片處理框架
- 包含的功能:圖片下載、圖片緩存、下載進度監聽、gif處理等等
- 用法極其簡單,功能十分強大,大大提高了網絡圖片的處理效率
- 國內超過90%的iOS項目都有它的影子
- 框架地址:https://github.com/rs/SDWebImage
獲得框架
- 進入終端
- 輸入以下命令
git clone --recursive https://github.com/rs/SDWebImage.git
第三方框架
介紹
- 由網絡大牛來編寫的框架程序
針對某一個具體的技術問題
,提供完善的解決方案
特點
- 功能強大
- 有非常好的錯誤處理
持續
升級維護
選擇依據
- 看懂源程序
- 如果有時間,要儘量閱讀常用框架的源程序並記錄筆記
- 看人數
- 看口碑
- 如果大家都說好,那就大膽的用
使用
- 工作後,往死裏用
- 學習中,儘量看懂源程序
- 獲取框架
- http://github.com 全世界優秀的 iOS 第三方框架幾乎都能找到
- 導入框架
- 直接拖拽
- 編譯,由於絕大多數第三方框架會有對其他框架的依賴,先編譯確認能夠正常使用
- 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 做緩存一定要保證能夠有恢復的通道!