19

私の質問に対する答えが見つかりません、何かが恋しいかもしれません...

URLを要求するとき、応答がキャッシュからのものかネットからのものかを知る必要があります。

ステータスコードは304または200ですか?(ただし、AFNetworking常に200に応答します)

から""ASIHTTPRequestをチェックしていたので、これは完璧でした。didUseCachedResponseASIHTTPRequest

4

4 に答える 4

24

応答がキャッシュから返されたのか、AFNetworking2.0を使用していないのかを判断するための解決策を見つけたと思います。サーバーから新しい応答が返されるたびに(304ではなくステータス200)、cacheResponseBlockのプロパティであるAFHTTPRequestOperationが呼び出されることがわかりました。応答をキャッシュする必要がある場合はブロックを返しNSCachedURLResponse、キャッシュしない場合はnilを返す必要があります。このようにして、応答をフィルタリングし、それらの一部のみをキャッシュできます。この場合、サーバーからのすべての応答をキャッシュしています。秘訣は、サーバーが304を送信し、応答がキャッシュからロードされるときに、このブロックが呼び出されないことです。だから、これは私が使用しているコードです:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

BOOL __block responseFromCache = YES; // yes by default

void (^requestSuccessBlock)(AFHTTPRequestOperation *operation, id responseObject) = ^(AFHTTPRequestOperation *operation, id responseObject) {
    if (responseFromCache) {
        // response was returned from cache
        NSLog(@"RESPONSE FROM CACHE: %@", responseObject);
    }
    else {
        // response was returned from the server, not from cache
        NSLog(@"RESPONSE: %@", responseObject);
    }
};

void (^requestFailureBlock)(AFHTTPRequestOperation *operation, NSError *error) = ^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"ERROR: %@", error);
};

AFHTTPRequestOperation *operation = [manager GET:@"http://example.com/"
                                      parameters:nil
                                         success:requestSuccessBlock
                                         failure:requestFailureBlock];

[operation setCacheResponseBlock:^NSCachedURLResponse *(NSURLConnection *connection, NSCachedURLResponse *cachedResponse) {
    // this will be called whenever server returns status code 200, not 304
    responseFromCache = NO;
    return cachedResponse;
}];

この解決策は私にとってはうまくいき、今のところ問題は見つかりませんでした。しかし、私の解決策に対してより良いアイデアや反対意見がある場合は、遠慮なくコメントしてください!

于 2014-02-04T15:05:54.657 に答える
2

アップルはそれがキャッシュから来ているかどうかをあなたに知られたくないようです。

リクエストに関連付けられた変更日を保存する方法を見つけました。AFNetWorkingが回答したときにこの日付を比較します。

私が意図したほどきれいではありませんが、動作します...

于 2012-09-03T08:09:48.427 に答える
1

AFNetworkingで成功として扱われるべきステータスコードを指定する方法があります。これは応答のシリアル化によって行われます。コードは次のとおりです。

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

AFHTTPResponseSerializer *respSerializer = [AFHTTPResponseSerializer serializer];
NSMutableIndexSet *responseCodes = [NSMutableIndexSet indexSet];
[responseCodes addIndex:200];
[responseCodes addIndex:304];

[operation setResponseSerializer:respSerializer];

このコードを使用すると、AFNetworkingは304を成功として扱います

于 2015-05-20T22:52:51.997 に答える
1

URLCacheクラスを作成し、storeCachedResponseメソッドをオーバーライドします

class MyURLCache: URLCache {
    override func storeCachedResponse(_ cachedResponse: CachedURLResponse, for request: URLRequest) {

        //adding caching header if needed
        var headers = response.allHeaderFields
        headers.removeValue(forKey: "Cache-Control")
        headers["Cache-Control"] = "max-age=\(5 * 60)" //5 min

        //the trick
        if (headers["isCachedReponse"] == nil){
            headers["isCachedReponse"] = "true"
        }

        if let
            headers = headers as? [String: String],
            let newHTTPURLResponse = HTTPURLResponse(url: response.url!, statusCode: response.statusCode, httpVersion: "HTTP/1.1", headerFields: headers) {
            let newCachedResponse = CachedURLResponse(response: newHTTPURLResponse, data: cachedResponse.data)
            super.storeCachedResponse(newCachedResponse, for: request)
        }
    }
}

AppDelegateでURLCacheとURLCache.sharedを設定します

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
        let cache = MyURLCache(memoryCapacity: 1024 * 1024 * 500, diskCapacity: 1024 * 1024 * 500, diskPath: nil)
        URLCache.shared = cache
        return true
    }
}

応答コールバックで、応答コンテンツのヘッダーが「newResponse」キーかどうかを確認します

if (response.allHeaderFields["isCachedReponse"] == nil){
      print("not cache")
} else {
      print("cache")
}

AFNetworkingのすべてのバージョンで動作します

于 2019-05-13T13:36:27.577 に答える