Question

J'ai une question. Peut-être 2 questions.

premier concerne cette pièce de code:

-(void)isLoggedIn {
NSString *urlString = [NSString stringWithFormat:@"%@%@%@", kBaseURL, kAPI, kUserIsLogged];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];
}

J'aimerais que cette méthode ne soit pas un vide, j'aimerais que cela retourne un bool ou quelque chose que je peux utiliser comme: l'utilisateur est connecté> OK fais quelque chose quelque part dans l'application; L'utilisateur n'est pas connecté> OK Invitez l'utilisateur à un écran où il peut introduire ses informations d'identification et connecter.

La deuxième question est liée à cette pièce de code:

-(void)detail {
NSString *urlString = [NSString stringWithFormat:@"%@%@%@", kBaseURL, kAPI, kUser];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];
}

J'aimerais que cette méthode me renvoie un NSARRAY avec le JSON analysé, que je peux utiliser partout où je veux.

Ces méthodes sont contenues dans un modèle appelé NetworkModel (sous-classe NsObject). Je me demande simplement pourquoi je devrais tout faire à l'intérieur des blocs. Je devrais avoir des morceaux interagir avec le réseau partout sur la place et non organisé dans un lieu / classe unique. Y-a-t-il un moyen de faire ça. Je ne veux pas avoir 5 lignes de demande de toutes les priorités. Je veux définir des méthodes que je peux appeler à partir de n'importe quel point de vue (importer évidemment les fichiers d'en-tête si nécessaire).

Toute suggestion? Merci de conseils!

Était-ce utile?

La solution

Vous pouvez le faire avec 2 approches, une modification de vos méthodes afin d'utiliser des blocs ou d'utiliser un sémaphore pour attendre la demande ASYNC:

avec sémaphore (la laid de manière laide)

-(BOOL)isLoggedIn {

__block BOOL isLoggedIn;
 dispatch_semaphore_t waiter = dispatch_semaphore_create(0);

NSString *urlString = [NSString stringWithFormat:@"%@%@%@", kBaseURL, kAPI, kUserIsLogged];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", responseObject);
    isLoggedIn = YES;
    dispatch_semaphore_signal(waiter);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
    isLoggedIn = NO;
    dispatch_semaphore_signal(waiter);

}];

dispatch_group_wait(waiter, DISPATCH_TIME_FOREVER);
return isLoggedIn;
}

la bonne façon de le faire

-(void)isLoggedIn:(void(^)(BOOL isLoggedIn))completionBlock {
NSString *urlString = [NSString stringWithFormat:@"%@%@%@", kBaseURL, kAPI, kUserIsLogged];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", responseObject);
    completionBlock(YES);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
    completionBlock(NO);
}];
}

Pour votre deuxième question, vous pouvez définir une variable de bloc de votre classe de réseau qui sera appelée lorsque la demande est terminée ou échoue.

Quoi qu'il en soit, je pense que vous n'êtes pas très familier avec les blocs (en raison de votre deuxième question) et je pense qu'après quelques blocs, vous commencerez à les aimer et que vous verrez que le code n'est pas compliqué si vous avez de petits extraits de codeCela effectuera la demande et l'analyse, vous verrez également que c'est si facile de les déboguer et de trouver les problèmes, je veux dire, c'était également mon cas lorsque j'ai commencé à travailler avec des blocs.

à l'aide d'une variable de bloc

@interface YourNetworkClass:NSObject {
void(^resultHandlerBlock)(NSArray *results); //this block has as param a NSArray, you can change it to whatever you want
}

-(void)setResultHandlerBlock:(void(^)(NSArray *array))handlerBlock;

@implementation YourNetworkClass

-(void)setResultHandlerBlock:(void(^)(NSArray *array))handlerBlock {
resultHandlerBlock = block;
}

-(void)anotherMethodThatDoesNetworkOperationsAndReturnsAnArray {
 ....
 resultHandlerBlock(arrayOfResults);
}


@interface AViewControllerThatUseNetwork: UIViewController {
}

@implementation AViewControllerThatUseNetwork 

-(void)initNetworkClass {
  YourNetworkClass *networkClass = [[YourNetworkClass alloc] init]; //or other init methods
  [networkClass setResultHandlerBlock:^(NSArray *results) {
   //do whatever you want with the array
}];
}

Autres conseils

J'ai demandé quelque chose de similaire au dos.Je crois que vous trouverez votre solution là-bas. Blocs de passage à une méthode Afnetworking?

En général, vous devrez changer votre façon de penser que vous devez obtenir les données de "si elles sont connectées à revenir bool" à "vérifier si je peux vous connecter, si cela échoue à faire quelque chose dans le bloc de travail Afnet.

Le lien ci-dessus répond également à votre deuxième question.

Vos méthodes doivent prendre un bloc (ou deux) qui sera exécutée à partir des blocs de réussite (ou d'échec) de l'Afnet.Cette approche embrasse la nature asynchrone de ce que vous essayez de faire.Vous ne pouvez pas ajouter de valeurs de retour aux méthodes à cause de cette asynchronicité.


Donc, vous modifiez votre méthode pour:

-(void)isLoggedInWithCompletion:(LoginCompletionBlock)completion {
    ...

    [manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"JSON: %@", responseObject);
        completion(/* whatever parameters your block specifies */);
    } ...
}

Donc, peu de mise à jour sur la situation (merci de toutes les suggestions précieuses..Merci les gars!). Maintenant, mon code ressemble à ceci (dans mon réseauModel.m, évidemment, j'ai ajouté la méthode à NetworkModel.h afin que je puisse l'appeler n'importe où):

-(void)isLoggedIn:(void(^)(BOOL isLoggedIn))completionBlock {
NSString *urlString = [NSString stringWithFormat:@"%@%@%@", kBaseURL, kAPI, kUserIsLogged];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", responseObject);
    if ([[NSString stringWithFormat:@"%@", responseObject] isEqualToString:@"true"]) {
        completionBlock(YES);
    } else {
       completionBlock(NO);
    }
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
    completionBlock(NO);
}];
}

dans mon appdelegate.h j'ai inclus mon réseauModel.h et dans mon appdelegate.m, j'ai maintenant le code suivant:

[[self model] isLoggedIn:^(BOOL isLoggedIn) {
    if (isLoggedIn == YES) {
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        UIViewController *controller = [storyboard instantiateViewControllerWithIdentifier:@"Start01"];
        [self.window setRootViewController:controller];
    } else {
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        UIViewController *controller = [storyboard instantiateViewControllerWithIdentifier:@"Start00"];
        [self.window setRootViewController:controller];
    }    
}];

Et cela fonctionne un peu bien. Mais maintenant j'ai une autre question à ce sujet. Quand je gère l'application, il y a quelque chose de bizarre qui se passe. Dès que cela récupère les informations sur l'état de la connexion de l'utilisateur, il passe à partir de VC (le contrôleur initialview désigné - Start00 sur mon storyboard) à VC (LogNDInvc - Start01 sur mon storyboard). Y a-t-il une façon de ne pas montrer ce peu de saut à l'utilisateur? Ou c'est un comportement normal? Maintenant, l'utilisateur voit une seconde le premier écran, puis l'écran qu'il devrait réellement voir (car il est connecté).

Mais je suppose que le moyen le plus simple de travailler avec des blocs et tout cela est de les utiliser à droite où j'en ai besoin. Au lieu d'essayer de les encapsuler dans des méthodes ou des cours ou autre chose. Dès que les données sont là, je ferai ce que j'ai, directement à l'intérieur du succès ou du bloc d'échec. Est-ce que je pense bien?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top