天天看點

iOS網絡加載圖檔緩存與SDWebImage

加載網絡圖檔可以說是網絡應用中必備的。如果單純的去下載下傳圖檔,而不去做多線程、緩存等技術去優化,加載圖檔時的效果與使用者體驗就會很差。

一、自己實作加載圖檔的方法

tips:

*iOS中所有網絡通路都是異步的.(自己開線程去下載下傳) *普通為模型增加UIImage屬性的方法做的是記憶體緩存(下次啟動還需要從網絡重新加載), 而要做本地緩存的話,還要自己手動存儲網絡上下載下傳的圖檔. *為了加快通路, 還需要自己去弄緩存.(記憶體緩存或者本地緩存) *當圖檔沒有下載下傳完成時,還要設定占位圖檔。

以下代碼用NSOperation開異步線程下載下傳圖檔,當下載下傳完成時替換占位圖檔。

<code>01.</code><code>//</code>

<code>02.</code><code>//  XNViewController.m</code>

<code>03.</code><code>//  加載網絡圖檔, 普通的用NSOperation來做.</code>

<code>04.</code><code>//</code>

<code>05.</code><code>//  Created by neng on 14-7-7.</code>

<code>06.</code><code>//  Copyright (c) 2014年 neng. All rights reserved.</code>

<code>07.</code><code>//</code>

<code>08.</code> 

<code>09.</code><code>#</code><code>import</code> <code>"XNViewController.h"</code>

<code>10.</code><code>#</code><code>import</code> <code>"XNApp.h"</code>

<code>11.</code> 

<code>12.</code><code>@interface</code> <code>XNViewController ()</code>

<code>13.</code><code>@property</code> <code>(nonatomic, strong) NSArray *appList;</code>

<code>14.</code><code>@property</code> <code>(nonatomic, strong) NSOperationQueue *queue;</code>

<code>15.</code><code>@end</code>

<code>16.</code> 

<code>17.</code><code>@implementation</code> <code>XNViewController</code>

<code>18.</code><code>#pragma mark - 懶加載</code>

<code>19.</code> 

<code>20.</code><code>- (NSOperationQueue *)queue {</code>

<code>21.</code><code>if</code> <code>(!_queue) _queue = [[NSOperationQueue alloc] init];</code>

<code>22.</code><code>return</code> <code>_queue;</code>

<code>23.</code><code>}</code>

<code>24.</code> 

<code>25.</code><code>//可抽取出來寫到模型中</code>

<code>26.</code><code>- (NSArray *)appList {</code>

<code>27.</code><code>if</code> <code>(!_appList) {</code>

<code>28.</code><code>//1.加載plist到數組中</code>

<code>29.</code><code>NSURL *url = [[NSBundle mainBundle] URLForResource:@</code><code>"apps.plist"</code> <code>withExtension:nil];</code>

<code>30.</code><code>NSArray *array = [NSArray arrayWithContentsOfURL:url];</code>

<code>31.</code><code>//2.周遊數組</code>

<code>32.</code><code>NSMutableArray *arrayM = [NSMutableArray array];</code>

<code>33.</code><code>[array enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {</code>

<code>34.</code><code>[arrayM addObject:[XNApp appWithDict:obj]];  </code><code>//數組中存放的是字典, 轉換為app對象後再添加到數組</code>

<code>35.</code><code>}];</code>

<code>36.</code><code>_appList = [arrayM copy];</code>

<code>37.</code><code>}</code>

<code>38.</code><code>return</code> <code>_appList;</code>

<code>39.</code><code>}</code>

<code>40.</code> 

<code>41.</code><code>- (</code><code>void</code><code>)viewDidLoad {</code>

<code>42.</code><code>[</code><code>super</code> <code>viewDidLoad];</code>

<code>43.</code> 

<code>44.</code><code>self.tableView.rowHeight = </code><code>88</code><code>;</code>

<code>45.</code> 

<code>46.</code><code>//    NSLog(@"appList-%@",_appList);</code>

<code>47.</code><code>}</code>

<code>48.</code> 

<code>49.</code><code>#pragma mark - 資料源方法</code>

<code>50.</code><code>- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {</code>

<code>51.</code><code>return</code> <code>self.appList.count;</code>

<code>52.</code><code>}</code>

<code>53.</code> 

<code>54.</code><code>- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {</code>

<code>55.</code><code>static</code> <code>NSString *ID = @</code><code>"Cell"</code><code>;</code>

<code>56.</code><code>UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];</code>

<code>57.</code> 

<code>58.</code><code>//用模型來填充每個cell</code>

<code>59.</code><code>XNApp *app = self.appList[indexPath.row];</code>

<code>60.</code><code>cell.textLabel.text = app.name;  </code><code>//設定文字</code>

<code>61.</code> 

<code>62.</code><code>//設定圖像: 模型中圖像為nil時用預設圖像,并下載下傳圖像. 否則用模型中的記憶體緩存圖像.</code>

<code>63.</code><code>if</code> <code>(!app.image) {</code>

<code>64.</code><code>cell.imageView.image = [UIImage imageNamed:@</code><code>"user_default"</code><code>];</code>

<code>65.</code> 

<code>66.</code><code>[self downloadImg:indexPath];</code>

<code>67.</code><code>}</code>

<code>68.</code><code>else</code> <code>{</code>

<code>69.</code><code>//直接用模型中的記憶體緩存</code>

<code>70.</code><code>cell.imageView.image = app.image;</code>

<code>71.</code><code>}</code>

<code>72.</code><code>//  NSLog(@"cell--%p", cell);</code>

<code>73.</code> 

<code>74.</code><code>return</code> <code>cell;</code>

<code>75.</code><code>}</code>

<code>76.</code> 

<code>77.</code><code>/**始終記住, 通過模型來修改顯示. 而不要試圖直接修改顯示*/</code>

<code>78.</code><code>- (</code><code>void</code><code>)downloadImg:(NSIndexPath *)indexPath {</code>

<code>79.</code><code>XNApp *app  = self.appList[indexPath.row]; </code><code>//取得改行對應的模型</code>

<code>80.</code> 

<code>81.</code><code>[self.queue addOperationWithBlock: ^{</code>

<code>82.</code><code>NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]]; </code><code>//得到圖像資料</code>

<code>83.</code><code>UIImage *image = [UIImage imageWithData:imgData];</code>

<code>84.</code> 

<code>85.</code><code>//在主線程中更新UI</code>

<code>86.</code><code>[[NSOperationQueue mainQueue] addOperationWithBlock: ^{</code>

<code>87.</code><code>//通過修改模型, 來修改資料</code>

<code>88.</code><code>app.image = image;</code>

<code>89.</code><code>//重新整理指定表格行</code>

<code>90.</code><code>[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];</code>

<code>91.</code><code>}];</code>

<code>92.</code><code>}];</code>

<code>93.</code><code>}</code>

<code>94.</code> 

<code>95.</code><code>@end</code>

上述代碼隻是做了記憶體緩存,而每次重新進入應用時,還會從網上重新下載下傳。如果要繼續優化上面的代碼,需要自己去實作本地緩存。

二、使用第三方架構SDWebImage。(非常優秀)

*特點 :依賴的庫很少.功能全面。 *自動實作磁盤緩存: *緩存圖檔名字是以MD5進行加密的後的名字進行命名.(因為加密那堆字串是唯一的) *[imageViewsd_setImageWithURL:v.fullImageURL placeholderImage:[UIImage imageNamed:@”xxxxx”]]. *就一個方法就實作了多線程帶緩沖等效果.(可用帶參數的方法,具體可看頭檔案)

用SDWebImage修改上面的方法後的代碼可簡化為:

<code>01.</code><code>#pragma mark - 資料源方法</code>

<code>02.</code><code>- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {</code>

<code>03.</code><code>return</code> <code>self.appList.count;</code>

<code>04.</code><code>}</code>

<code>05.</code> 

<code>06.</code><code>- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {</code>

<code>07.</code><code>static</code> <code>NSString *ID = @</code><code>"Cell"</code><code>;</code>

<code>08.</code><code>UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];</code>

<code>09.</code> 

<code>10.</code><code>//用模型來填充每個cell</code>

<code>11.</code><code>XNApp *app = self.appList[indexPath.row];</code>

<code>12.</code><code>cell.textLabel.text = app.name;  </code><code>//設定文字</code>

<code>13.</code> 

<code>14.</code><code>//  //設定圖像: 模型中圖像為nil時用預設圖像,并下載下傳圖像. 否則用模型中的記憶體緩存圖像.</code>

<code>15.</code><code>//  if (!cell.imageView.image) {</code>

<code>16.</code><code>//      cell.imageView.image = [UIImage imageNamed:@"user_default"];</code>

<code>17.</code><code>//</code>

<code>18.</code><code>//      [self downloadImg:indexPath];</code>

<code>19.</code><code>//  }</code>

<code>20.</code><code>//  else {</code>

<code>21.</code><code>//      //直接用模型中的記憶體緩存</code>

<code>22.</code><code>//      cell.imageView.image = app.image;</code>

<code>23.</code><code>//  }</code>

<code>25.</code> 

<code>26.</code><code>//使用SDWebImage來完成上面的功能. 針對ImageView.</code>

<code>27.</code><code>//一句話, 自動實作了異步下載下傳. 圖檔本地緩存. 網絡下載下傳. 自動設定占位符.</code>

<code>28.</code><code>[cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.icon] placeholderImage:[UIImage imageNamed:@</code><code>"user_default"</code><code>]];</code>

<code>29.</code> 

<code>30.</code> 

<code>31.</code><code>return</code> <code>cell;</code>

<code>32.</code><code>}</code>

<code>33.</code> 

<code>34.</code><code>/**始終記住, 通過模型來修改顯示. 而不要試圖直接修改顯示*/</code>

<code>35.</code><code>//- (void)downloadImg:(NSIndexPath *)indexPath {</code>

<code>36.</code><code>//  XNApp *app  = self.appList[indexPath.row]; //取得改行對應的模型</code>

<code>37.</code><code>//</code>

<code>38.</code><code>//  [self.queue addOperationWithBlock: ^{</code>

<code>39.</code><code>//      NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]]; //得到圖像資料</code>

<code>40.</code><code>//      UIImage *image = [UIImage imageWithData:imgData];</code>

<code>41.</code><code>//</code>

<code>42.</code><code>//      //在主線程中更新UI</code>

<code>43.</code><code>//      [[NSOperationQueue mainQueue] addOperationWithBlock: ^{</code>

<code>44.</code><code>//          //通過修改模型, 來修改資料</code>

<code>45.</code><code>//          app.image = image;</code>

<code>46.</code><code>//          //重新整理指定表格行</code>

<code>47.</code><code>//          [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];</code>

<code>48.</code><code>//      }];</code>

<code>49.</code><code>//  }];</code>

<code>50.</code><code>//}</code>

<code>51.</code> 

<code>52.</code><code>@end</code>

SDWebImage中的一些參數: *SDWebImageRetryFailed = 1&lt;&lt; 0, 預設選項,失敗後重試 *SDWebImageLowPriority = 1&lt;&lt; 1, 使用低優先級 *SDWebImageCacheMemoryOnly = 1&lt;&lt; 2, 僅僅使用記憶體緩存 *SDWebImageProgressiveDownload = 1&lt;&lt; 3, 顯示現在進度 *SDWebImageRefreshCached = 1&lt;&lt; 4, 重新整理緩存 *SDWebImageContinueInBackground =1 &lt;&lt; 5, 背景繼續下載下傳圖像 *SDWebImageHandleCookies = 1&lt;&lt; 6, 處理Cookie *SDWebImageAllowInvalidSSLCertificates= 1 &lt;&lt; 7, 允許無效的SSL驗證 *SDWebImageHighPriority = 1&lt;&lt; 8, 高優先級 *SDWebImageDelayPlaceholder = 1&lt;&lt; 9 延遲顯示占位圖檔

出處:http://blog.csdn.net/xn4545945

如何聯系我:【萬裡虎】www.bravetiger.cn

【QQ】3396726884 (咨詢問題100元起,幫助解決問題500元起)

【部落格】http://www.cnblogs.com/kenshinobiy/

繼續閱讀