你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 玩轉iOS開發 - 數據緩存

玩轉iOS開發 - 數據緩存

編輯:IOS開發綜合

Why Cache

有時候,對同一個URL請求多次,返回的數據可能都是一樣的,比如服務器上的某張圖片,無論下載多少次,返回的數據都是一樣的。

這裡寫圖片描述

上面的情況會造成以下問題

(1)用戶流量的浪費
(2)程序響應速度不夠快

解決上面的問題,一般考慮對數據進行緩存。

數據緩存

為了提高程序的響應速度,可以考慮使用緩存(內存緩存\硬盤緩存)r

這裡寫圖片描述

第一次請求數據時,內存緩存中沒有數據,硬盤緩存中沒有數據。

緩存數據的過程:

這裡寫圖片描述

? 當服務器返回數據時,需要做以下步驟
(1)使用服務器的數據(比如解析、顯示)
(2)將服務器的數據緩存到硬盤(沙盒)
 此時緩存的情況是:內存緩存中有數據,硬盤緩存中有數據。

? 再次請求數據分為兩種情況:
(1)如果程序並沒有被關閉,一直在運行
      請求數據-> 內存數據
(2)如果程序重新啟動
    請求數據->硬盤數據-> 再次請求數據-> 內存數據

提示:數據從硬盤讀入內存-> 程序開啟-> 內存中一直有數據

緩存的實現

說明:

? 由於GET請求一般用來查詢數據
? POST請求一般是發大量數據給服務器處理(變動性比較大)
=>因此一般只對GET請求進行緩存,而不對POST請求進行緩存

? 在iOS中,可以使用NSURLCache類緩存數據
? iOS 5之前:只支持內存緩存。從iOS 5開始:同時支持內存緩存和硬盤緩存

NSURLCache

iOS中得緩存技術用到了NSURLCache類。
? 緩存原理:一個NSURLRequest對應一個NSCachedURLResponse
? 緩存技術:把緩存的數據都保存到數據庫中。

NSURLCache的常見用法

(1)獲得全局緩存對象(沒必要手動創建)

    NSURLCache *cache = [NSURLCache sharedURLCache]; 

(2)設置內存緩存的最大容量(字節為單位,默認為512KB)

    - (void)setMemoryCapacity:(NSUInteger)memoryCapacity;

(3)設置硬盤緩存的最大容量(字節為單位,默認為10M)

- (void)setDiskCapacity:(NSUInteger)diskCapacity;

(4)硬盤緩存的位置:

    沙盒/Library/Caches

(5)取得某個請求的緩存

- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request; 

(6)清除某個請求的緩存

    - (void)removeCachedResponseForRequest:(NSURLRequest *)request;

(7)清除所有的緩存

- (void)removeAllCachedResponses;

緩存GET請求

要想對某個GET請求進行數據緩存,非常簡單
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

// 設置緩存策略
request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;

只要設置了緩存策略,系統會自動利用NSURLCache進行數據緩存

7種緩存策略

? NSURLRequestUseProtocolCachePolicy // 默認的緩存策略(取決於協議)

? NSURLRequestReloadIgnoringLocalCacheData // 忽略緩存,重新請求

? NSURLRequestReturnCacheDataElseLoad// 有緩存就用緩存,沒有緩存就重新請求  

? NSURLRequestReturnCacheDataDontLoad// 有緩存就用緩存,沒有緩存就不發請求,當做請求出錯處理(用於離線模式)

NSURLRequestReloadIgnoringLocalAndRemoteCacheData // 未實現
NSURLRequestReloadRevalidatingCacheData // 未實現
NSURLRequestReloadIgnoringLocalAndRemoteCacheData // 未實現

緩存的注意事項

緩存的設置需要根據具體的情況考慮,如果請求某個URL的返回數據:

    (1)經常更新:不能用緩存!比如股票、彩票數據
    (2)一成不變:果斷用緩存
    (3)偶爾更新:可以定期更改緩存策略 或者 清除緩存

提示:如果大量使用緩存,會越積越大,建議定期清除緩存

GET緩存

在appDelegate中設置網絡緩存大小 實現get 緩存:
如果從服務器加載數據,通過etag 判斷加載數據與緩存是否相同 從本地加載數據
    //
    //  AppDelegate.m
    //  A-get緩存請求
    //
    //  Created by Mr.Sunday on 15/4/27.
    //  Copyright (c) 2015年 Novogene. All rights reserved.
    //

    #import "AppDelegate.h"

    @interface AppDelegate ()

    @end

    @implementation AppDelegate
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
    {

        /*===============設置網絡緩存==============*/
        /**
         內存緩存->4M
         磁盤緩存->20M
         diskPath 如果是 nil,會緩存到 cached 的 bundleId 目錄下

         只要在 AppDelegate 中加入以下兩句話,今後所有的緩存處理,就不需要管了!
         */

        NSURLCache *cathe = [[NSURLCache alloc] initWithMemoryCapacity:4*1024*1024 diskCapacity:20*1024*1024 diskPath:nil];
        [NSURLCache setSharedURLCache:cathe];

        /**
         SDWebImage 的緩存
         1. 緩存時間:1周
         2. 處理緩存文件,監聽系統退出到後台的事件
         - 遍歷緩存文件夾,刪除所有過期的文件
         - 繼續遍歷緩存文件夾,將最大的文件刪除,一直刪除到緩存文件的大小和指定的“磁盤限額”一致,停止
         */
        return YES;
    }
    //
    //  ViewController.m
    //  A-get緩存請求
    //
    //  Created by Mr.Sunday on 15/4/27.
    //  Copyright (c) 2015年 Novogene. All rights reserved.
    //

    #import "ViewController.h"

    @interface ViewController ()

    @property (nonatomic, weak) IBOutlet UIImageView *iconView;
    //服務器返回的etag
    @property (nonatomic, copy) NSString *etag;
    //清楚所有緩存
    - (void)removeAllCachedResponses;

    @end

    @implementation ViewController

    - (void)viewDidLoad 
    {
        [super viewDidLoad];
    }

    /**
     1. 請求的緩存策略使用 >NSURLRequestReloadIgnoringCacheData<,忽略本地緩存
     2. 服務器響應結束後,要記錄 Etag,服務器內容和本地緩存對比是否變化的重要依據!
     3. 在發送請求時,設置 If-None-Match,並且傳入 etag
     4. 連接結束後,要判斷響應頭的狀態碼,如果是 304,說明本地緩存內容沒有發生變化
     */

    /*==================從本地緩存加載數據==============*/
    /*
     NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
     self.iconView.image = [UIImage imageWithData:cachedResponse.data];
     */
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        NSURL *url = [NSURL URLWithString:@"http://mrsunday.local/ml.png"];

        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];

        /**
         *設置請求頭->所有的請求頭都是通過這種方法設置的
         *如果etag length不為0,說明已經有緩存了
         */
        if (self.etag.length > 0)
        {
            NSLog(@"設置 etag: %@", self.etag);
            [request setValue:self.etag forHTTPHeaderField:@"IF-None-Match"];
        }

        //請求的默認方法是get(高頻使用)
        NSLog(@"%@",request.HTTPMethod);

        /**
         *Etag = "\"4a0b9-514a2d804bd40\"";
         *可以在請求中增加一個 etag 跟服務器返回的 etag 進行對比
         *就能夠判斷服務器對應的資源是否發生變化,具體更新的時間,由request自行處理
         */

        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
        {
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            /**
             *allHeaderFields 所有相應頭子端
             */
            NSLog(@"%@ %@", httpResponse.allHeaderFields, httpResponse);

            /**
             *如果服務器的狀態碼是304,說明數據已經被緩存,服務器不再需要返回數據
             *需要從本地緩存獲取被緩存的數據
             */
            if (httpResponse.statusCode == 304)
            {
                NSLog(@"load local database");

                /**
                 *針對http訪問的一個緩存類,提供了一個單例
                 *拿到被緩存的響應
                 */
                NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
                self.iconView.image = [UIImage imageWithData:cachedResponse.data];

                return;
            }

            //記錄etag
            self.etag = httpResponse.allHeaderFields[@"etag"];
            self.iconView.image = [UIImage imageWithData:data];
        }];
    }

    //記得要清除緩存請求!
    - (void)removeAllCachedResponses
    {
        [self removeAllCachedResponses];
    }
    @end
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved