2013-09-28 3 views
4

J'essaie de créer une sous-classe pour NSURLProtocol. Cependant, je remarque que je semble perdre la fonctionnalité de mise en cache lorsque j'inscris ma sous-classe, même si cela ne devrait rien faire. Par exemple, si je fais [NSURLConnection sendSynchronousRequest ...] plusieurs fois dans la même URL sans enregistrer la sous-classe, elle ne fait qu'une requête http réelle. Avec cette sous-classe enregistrée, il effectue une requête réseau à chaque fois.La mise en cache ne fonctionne pas avec NSURLProtocol personnalisé

Voici mon code:

@interface CustomURLProtocol : NSURLProtocol 
@property (nonatomic, strong) NSURLConnection *connection; 
@end 

@implementation CustomURLProtocol 

+ (BOOL)canInitWithRequest:(NSURLRequest *)request { 
    return [[[request URL] scheme] isEqualToString:@"http"] && 
      [NSURLProtocol propertyForKey:@"tagged" inRequest:request] == nil; 
} 

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { 
    return request; 
} 

- (void)startLoading { 
    NSMutableURLRequest *newRequest = [self.request mutableCopy]; 
    [NSURLProtocol setProperty:@YES forKey:@"tagged" inRequest:newRequest]; 
    self.connection = [NSURLConnection connectionWithRequest:newRequest delegate:self]; 
} 

- (void)stopLoading { 
    [self.connection cancel]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    [[self client] URLProtocol:self didLoadData:data]; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    [[self client] URLProtocol:self didFailWithError:error]; 
    self.connection = nil; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 
    [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:[[self request] cachePolicy]]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    [[self client] URLProtocolDidFinishLoading:self]; 
    self.connection = nil; 
} 
@end 

Répondre

1

La question ici était pas ce que je pensais. Le vrai problème est que les redirections sont pas traitées correctement, puisque le code suivant était pas là:

- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response { 
    [[self client] URLProtocol:self wasRedirectedToRequest:request redirectResponse:response]; 
    return request; 
} 

Sans ce code, réoriente n'étaient pas mises en cache en fait la demande de façon séquentielle à demandes d'une URL redirigée comme résultat wikipedia.com dans les redirections à chaque fois.

1

Je pense que la ligne que vous avez ajoutée est juste pour ignorer votre NSURLProtocol personnalisé. Après avoir ajouté cette méthode, les méthodes connectionDelegate sont-elles encore appelées?

Mise à jour: Enfin compris cela. C'est la raison. Je l'ai fait fonctionner après avoir ajouté cette partie dans startLoading.

NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:self.request]; 
    if (cachedResponse) { 
     [self connection:nil didReceiveResponse:[cachedResponse response]]; 
     [self connection:nil didReceiveData:[cachedResponse data]]; 
     [self connectionDidFinishLoading:nil]; 
    } else { 
     _connection = [NSURLConnection connectionWithRequest:newRequest delegate:self]; 
    } 
+1

Je pense que la raison possible est que le protocole personnalisé NSURLProtocol n'est pas traité comme http du tout. Ensuite, la stratégie de cache envoyée par la requête est NSURLRequestUseProtocolCachePolicy par défaut et le système de chargement d'URL ne sait pas comment le mettre en cache, il les supprime donc tous. – jqyao

Questions connexes