NSURLRequestがデータをキャッシュしないようにしたり、リクエスト後にキャッシュされたデータを削除したりすることはできますか?


89

iPhoneでは、データのチャンクに対してNSURLRequestを使用してHTTPリクエストを実行します。オブジェクト割り当てが急上昇し、それに応じてデータを割り当てます。データを使い終わったら、それに応じて解放します。ただし、機器には解放されたデータが表示されません。

私の理論では、デフォルトではHTTPリクエストはキャッシュされますが、iPhoneアプリでこのデータをキャッシュしたくありません。

リクエスト後にこのキャッシュをクリアする方法、または最初にデータがキャッシュされるのを防ぐ方法はありますか?

以下のようにドキュメント化されたすべてのキャッシュポリシーを使用してみました。

NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
theRequest.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

しかし、メモリを解放するものは何もないようです!


キャッシュに関連していない可能性はありますか?データを検査して、リロードされるべきデータが実際に古いものかどうかを確認しましたか?多分あなたのネギは他の場所から来ています。NSURLRequestsをどのように初期化して解放しますか?これは問題の診断に役立つ場合があります。
lpfavreau、

参考までに–力ずくでファイルを削除したい場合、ここにそれを行うためのサンプルコードがあります:salesforce.stackexchange.com/a/69736
zekel

回答:


157

通常、このようなリクエストを作成する方が簡単です

NSURLRequest *request = [NSURLRequest requestWithURL:url
      cachePolicy:NSURLRequestReloadIgnoringCacheData
      timeoutInterval:60.0];

次に、接続を作成します

NSURLConnection *conn = [NSURLConnection connectionWithRequest:request
       delegate:self];

そして、デリゲートにconnection:willCacheResponse:メソッドを実装します。nilを返すだけで十分です。

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
  return nil;
}

ここにあなたの助けを本当にありがとう!ニック。
Nick Cartwright、

1
そのアイデアをありがとう-私はこのようなSOAP Webサービスを繰り返し呼び出していて、リークが何も問題がないことを示していなくても、制御不能にヒープを増大させていました。内部フレームワークからの多くのCFURL *オブジェクトがぶらぶらしていたので、私は数日間最適化し、最後にキャッシュを防止しようとしました。willCacheResponseからnilを返すことだけが機能しました。
Bron Davies

15
なぜ両方NSURLRequestReloadIgnoringCacheData 実行する必要があるのconnection:willCacheResponse:ですか?
ファブ

1
こんにちは、これをローカルコンテンツの読み込みに使用することは可能ですか?上記はNSUrlConnectionの場合ですが、NSUrlRequestを使用してローカルのHTMLデータをUIWebViewにロードしています。SQLiteからwebviewに入る画像があり、ページが読み込まれるたびにメモリが増加するため、キャッシュを拒否する必要があります。ありがとう。
ジム

7
@fabb、オーバーライドconnection:willCacheResponse:すると、応答をキャッシュに保存しないようにすることができます。NSURLRequestReloadIgnoringCacheData接続がキャッシュをチェックせずにリクエストをロードすることを指定します。前者はおそらくメモリ割り当ての管理に役立ちます。
Christopher Pickslay

12

Twitterから情報を要求したとき、アプリにも同じ問題があります。私の場合、これらの資格情報を保持する必要はなかったので、次のコードを使用して単純に消去します。

- (void) eraseCredentials{
NSURLCredentialStorage *credentialsStorage = [NSURLCredentialStorage sharedCredentialStorage];
NSDictionary *allCredentials = [credentialsStorage allCredentials];

//iterate through all credentials to find the twitter host
for (NSURLProtectionSpace *protectionSpace in allCredentials)
    if ([[protectionSpace host] isEqualToString:@"twitter.com"]){
        //to get the twitter's credentials
        NSDictionary *credentials = [credentialsStorage credentialsForProtectionSpace:protectionSpace];
        //iterate through twitter's credentials, and erase them all
        for (NSString *credentialKey in credentials)
            [credentialsStorage removeCredential:[credentials objectForKey:credentialKey] forProtectionSpace:protectionSpace];
    }
}

私はそれが誰かのために働くことを願っています:)


これは私の問題の完璧な解決策でした。再ログインの問題がありました。資格情報が保存され、NSURLConnectionによって自動的に送信されたためです。おかげで、これは
非常に

おかげで私にとってはとても助かります。あなたの提案に本当に感謝しています。実際、私の問題は、NSURLRequestがユーザー名とパスワードを保存していることです。したがって、これはキャッシュからユーザー資格情報を削除するのに役立ちます...
Nilesh Kikani

10

NSURLConnectionを使用する場合は、デリゲートを見てください。

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse

戻り値

キャッシュに格納する実際のキャッシュされた応答。デリゲートは、変更されていないcachedResponseを返すか、変更されたキャッシュされた応答を返すか、または接続に対してキャッシュされた応答を格納する必要がない場合はnilを返します。


ここにどうもありがとう。アプリのメモリフットプリントが突然半分になりました。ニック。
Nick Cartwright、

9

を使用している場合NSURLSession、リクエストとパラメーターがCache.dbiOS に書き込まれるのを防ぐための別のソリューションは、アプリのCachesディレクトリ内に作成されます。たとえばNSURLCache、セッションの構成のを0サイズのメモリと0サイズのディスクキャッシュに設定します。

let configuration = URLSessionConfiguration.default    
configuration.urlCache = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)
let session = URLSession(configuration: configuration)

または上記のようにグローバルキャッシュレベルで設定

URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)

おそらく、iOSによるディスクへの書き込みを停止するのはディスクサイズの0ですが、ポリシーがある場合は、reloadIgnoringLocalCacheDataおそらくメモリキャッシュにも興味がありません。

これにより、Caches/Cache.db(要求と応答)またはCaches/fsCachedData/フォルダー(応答データ)がまったく作成されなくなります。リクエストをディスクキャッシュに保存したくないので、セキュリティ上の理由からアプリでこのアプローチを採用することにしました。

リクエストのキャッシュのみを停止し、iOSのURLロードメカニズムからの応答データのキャッシュを保持する方法があることを誰かが知っている場合は、知りたいと思います。(私が言えることから、これに関するAPIまたは公式のドキュメントはありません)


7

単一のリクエストに固有でない場合(アプリ全体のキャッシュを無効にする必要がある場合)は、1つ以下が最適なオプションです。このコードをアプリデリゲートに追加するか、必要に応じてこのコードを追加します

        int cacheSizeMemory = 0*4*1024*1024; // 0MB
        int cacheSizeDisk = 0*32*1024*1024; // 0MB
        NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"];
        [NSURLCache setSharedURLCache:sharedCache];

7
私にとってはうまくいきますが、とにかく0になる乗算を行うのではなく、0を使用することができます。
ゲイリーリッチス

1
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] url];
[request setValue:@"no-store" forHTTPHeaderField:@"Cache-Control"];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];

サーバーが正しく実装されていると仮定すると、Cache-Control:no-storeヘッダーをリクエストに含めると、同じヘッダーのサーバー応答が生成さNSURLCacheれ、応答データがディスクに保存されなくなります。

したがって、NSURLCacheディスクキャッシングを無効にするショットガンアプローチは必要ありません。

PS:ヘッダーの追加は、次のようなすべてのHTTPフレームワークで機能するはずです。 AFNetworking

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.