Question

Je suis en train d'écrire une petite application iOS qui interroge un XML REST webservice. Le cadre de réseau utilisé est AFNetworking .

Situation

Pour interroger le webservice je AFHTTPClient sous-classé:

@interface MyApiClient : AFHTTPClient

et dans la mise en œuvre que je fais que disponible en singleton:

+ (MyApiClient *)sharedClient {
    static MySharedClient *_sharedClient = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _sharedClient = [[self alloc] initWithBaseUrl:[NSUrl URLWithString:@"http://url.to.the.webservice"]];
    });

    return self;
} 

et initWithBaseURL je dis AFNetworking d'attendre du contenu XML:

[self registerHTTPOperationClass:[AFXMLRequestOperation class]];

Maintenant, je peux appeler getPatch sur le singleton de mon ViewController et dans le bloc de succès commence mon analyse syntaxique XML retourné. Dans les méthodes NSXMLParserDelegate dans le ViewController je peux alors choisir les parties du XML que je suis intéressé et faire des choses avec elle.

Problème

Je veux avoir des méthodes dans mon HTTPClient singleton que tout poignée en rapport avec les modèles de données webservice et retour ou liste des modèles au lieu de XML.

Par exemple, je veux faire quelque chose comme ceci:

ServerModel *status = [[MyApiClient sharedClient] getServerStatus];

Le ApiClient alors appeler en interne le webservice, analyser le XML et retourner le modèle. Comment puis je faire ça? Normalement, je voudrais utiliser un délégué qui est appelé une fois que le XML est analysé, mais en raison de la nature singleton du ApiClient il pourrait y avoir plusieurs délégués?

quelqu'un L'espoir peut faire la lumière sur ce sujet, merci!

Était-ce utile?

La solution

(Toutes mes excuses à l'avance pour ce « tri de » réponse, mais nous travaillons à une meilleure solution ...)

Vous devez prendre un pas en arrière et pensez à votre conception avec soin.

Vous avez des problèmes parce que vous avez une idée que quelque chose dans vos besoins de conception à un singleton, mais soit:

1) qui n'est pas vraiment nécessaire,

2) quelque chose pourrait déjà exister qui le fait travail pour vous (par exemple, le HTTP lib que vous utilisez),

ou

3) Vous faire la mauvaise chose un singleton, ou vous ne l'avez pas portionné votre conception dans les parties appropriées pour fonctionner avec l'idée singleton

Alors, pouvez-vous me dire explicitement pourquoi vous allez pour une approche singleton? Est-il juste d'assurer qu'une demande de réseau ne peut se produire à la fois? Y at-il de la notion statefulness dans votre objet singleton? Ensuite, je mettrai à jour cette réponse ou un commentaire, etc.

( Digression: Je voudrais aussi ajouter que dans certains cas, il pourrait y avoir un véritable besoin d'un forte 'singleton - je veux dire qu'il ya vraiment une seule instance possible, et ce mécanisme est cuit directement dans votre objet, comme vous le faites - mais ce n'est pas l'alternative est un ' faible singleton, je veux dire par votre objet principal. qui fait réellement le travail a un avantage de cette faible idée singleton méthode init simple comme d'habitude, mais l'accès partagé à un objet commun passe par un autre objet, qui est une sorte de simple « usine » qui instancie / détient l'instance partagée. est que votre code est plus réutilisable dans des contextes différents - par exemple, vous pouvez décider de faire plusieurs requêtes HTTP / sessions en même temps à une date ultérieure - et il fait parfois des tests d'écriture moins problématiques)

.

Autres conseils

Utiliser des blocs au lieu des délégués.

De ma classe ApiClient:

- (void)getPath:(NSString *)path 
     parameters:(NSDictionary *)parameters 
        success:(void (^)(id response))success 
        failure:(void (^)(NSError *error))failure 
{   
    NSURLRequest *request = [self requestWithMethod:@"GET" path:path parameters:parameters];
    [self enqueueHTTPOperationWithRequest:request success:success failure:failure];
}

-(void)fetchAllUsersSuccess:(void (^)(id))success 
                     failure:(void (^)(NSError *))failure
{
    [self getPath:@"/api/mobile/user/" 
       parameters:nil 
          success:^(id response) {  

                      if([response isKindOfClass:[NSXMLParser class]]){
                          //parse here to new dict
                          success(newDict);
                      } else
                          success(response);

          } failure:^(NSError *error) {
              failure(error);
          }];
}

Maintenant, je peux l'utiliser comme:

ServiceApiClient *apiClient = [ServiceApiClient sharedClient];

[apiClient fetchAllUsersSuccess:^(id dict) {
    for (NSDictionary *object in [dict objectForKey:@"objects"]) {
        [ServiceUser addUserFromDictionary:object
                                 inContext:self.managedObjectContext];
    }
    NSError *error= nil;
    [self.managedObjectContext save:&error];
    if (error) {
        NSLog(@"%@", error);
    }
} failure:^(NSError * error) {
    NSLog(@"%@", error);
}];
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top