加載網絡圖檔可以說是網絡應用中必備的。如果單純的去下載下傳圖檔,而不去做多線程、緩存等技術去優化,加載圖檔時的效果與使用者體驗就會很差。
一、自己實作加載圖檔的方法
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<< 0, 預設選項,失敗後重試 *SDWebImageLowPriority = 1<< 1, 使用低優先級 *SDWebImageCacheMemoryOnly = 1<< 2, 僅僅使用記憶體緩存 *SDWebImageProgressiveDownload = 1<< 3, 顯示現在進度 *SDWebImageRefreshCached = 1<< 4, 重新整理緩存 *SDWebImageContinueInBackground =1 << 5, 背景繼續下載下傳圖像 *SDWebImageHandleCookies = 1<< 6, 處理Cookie *SDWebImageAllowInvalidSSLCertificates= 1 << 7, 允許無效的SSL驗證 *SDWebImageHighPriority = 1<< 8, 高優先級 *SDWebImageDelayPlaceholder = 1<< 9 延遲顯示占位圖檔
出處:http://blog.csdn.net/xn4545945
如何聯系我:【萬裡虎】www.bravetiger.cn
【QQ】3396726884 (咨詢問題100元起,幫助解決問題500元起)
【部落格】http://www.cnblogs.com/kenshinobiy/