Die Weise, die ich das gelöst habe, ist, alle meine Anfragen mit einem Codeblock zu verpacken, der das Zugangstoken bei Bedarf z.
einige typedefs für Erfolg und Misserfolg Blöcke hinzufügen:
typedef void (^YFRailsSaasApiClientSuccess)(AFJSONRequestOperation *operation, id responseObject);
typedef void (^YFRailsSaasApiClientFailure)(AFJSONRequestOperation *operation, NSError *error);
die Anforderungsmethode Dann ist:
- (void)getProductsWithSuccess:(YFRailsSaasApiClientSuccess)success failure:(YFRailsSaasApiClientFailure)failure {
NSLog(@"getProductsWithSuccess");
success = ^(AFJSONRequestOperation *operation, id responseObject) {
[self getPath:@"api/1/products"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"getProductsWithSuccess: success");
// TODO: handle response
if (success) {
success((AFJSONRequestOperation *)operation, responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"getProductsWithSuccess: failure");
if (failure) {
failure((AFJSONRequestOperation *)operation, error);
}
}];
};
[self refreshAccessTokenWithSuccess:success failure:failure];
}
Und die Methode, die für Token Ablauf überprüft und aktualisiert es erforderlich, wenn ist:
- (void)refreshAccessTokenWithSuccess:(YFRailsSaasApiClientSuccess)success failure:(YFRailsSaasApiClientFailure)failure {
NSLog(@"refreshAccessTokenWithSuccess");
if (self.credential == nil) {
if (failure) {
NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
[errorDetail setValue:@"Failed to get credentials" forKey:NSLocalizedDescriptionKey];
NSError *error = [NSError errorWithDomain:@"world" code:200 userInfo:errorDetail];
failure(nil, error);
}
return;
}
if (!self.credential.isExpired) {
NSLog(@"refreshAccessTokenWithSuccess: credential has not expired");
if (success) {
success(nil, nil);
}
return;
}
NSLog(@"refreshAccessTokenWithSuccess: refreshing credential");
[self authenticateUsingOAuthWithPath:@"oauth/token"
refreshToken:self.credential.refreshToken
success:^(AFOAuthCredential *newCredential) {
NSLog(@"Successfully refreshed OAuth credentials %@", newCredential.accessToken);
self.credential = newCredential;
[AFOAuthCredential storeCredential:newCredential
withIdentifier:self.serviceProviderIdentifier];
if (success) {
success(nil, nil);
}
}
failure:^(NSError *error) {
NSLog(@"An error occurred refreshing credential: %@", error);
if (failure) {
failure(nil, error);
}
}];
}
Der vollständige Quellcode ist auf GitHub: https://github.com/yellowfeather/rails-saas-ios.
Zusätzlich können Sie das Speichern der Anmeldeinformationen in den Setter der Eigenschaft verschieben. – conradev
Es scheint, dass dies von expires_in auf dem Token abhängig ist, das davon ausgeht, dass Ihre Uhr ziemlich synchron mit dem Server ist, selbst nach Netzwerkverzögerung (was ein Problem sein kann) und dass Ihr Server tatsächlich den expires_in Wert setzt richtig. expires_in wird empfohlen, ist aber in der Spezifikation nicht erforderlich. Dies bedeutet, dass auf Servern, die expires_in nicht unterstützen, die Aktualisierung durchgeführt werden sollte, nachdem ein Fehler für eine Anforderung mit dem Token erhalten wurde. Typisch ist der Fehler beim Auslösen einer Aktualisierung 401. Ich wollte nur bemerken, dass diese Lösung zwar funktioniert, aber nicht immer funktioniert. – ptoinson
@ Ptoinson Sie haben Recht und ich bin in diesem Problem, haben Sie ein Codebeispiel zu teilen, die eine Aktualisierung durchführt und senden Sie dann die Anfrage mit dem aktualisierten Token? Ich versuche AFNetworkingOperationDidFinishNotification zu beobachten, kann aber keine befriedigende Lösung finden. – Newcode