Pregunta

Tengo una pregunta. Tal vez 2 preguntas.

Primero se relaciona con esta pieza de código:

-(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);
}];
}

Me gustaría que este método no sea un vacío, me gustaría que regrese un bool o algo que pueda usar como: el usuario está conectado> OK Haz algo en algún lugar de la aplicación; El usuario no ha iniciado sesión> OK, solicite al usuario en una pantalla donde pueda presentar sus credenciales e iniciar sesión.

La segunda pregunta está relacionada con esta pieza de código:

-(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);
}];
}

Me gustaría que este método me devuelva un Nsarray con el JSON analizado, que puedo usar donde quiera.

Estos métodos se encuentran contenidos en un modelo llamado NetworkModel (Subclase NSOBJECT). Solo me pregunto por qué debería hacer todo lo que está dentro de los bloques. Debería tener piezas que interactúan con la red en todo el lugar, y no se organizaron en un lugar / clase única. Hay una manera de hacer eso. No quiero tener 5 líneas de solicitudes en cada ViewController. Quiero definir métodos que puedo llamar desde cualquier ViewController (obviamente importar los archivos de encabezado donde sea necesario).

¿Alguna sugerencia? ¡Gracias por el consejo!

¿Fue útil?

Solución

Puede hacerlo con 2 enfoques, uno cambie sus métodos para usar bloques o usar un semáforo para esperar la solicitud de ASYNC:

con semáforo (la forma fea)

-(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 forma correcta de hacerlo

-(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);
}];
}

Para su segunda pregunta, puede establecer una variable de bloque en su clase de redes que se llamarán cuando se complete la solicitud o falle.

De todos modos, creo que no está muy familiarizado con los bloques (debido a su segunda pregunta) y creo que después de unas pocas cuadras comenzará a gustarles y verá que el código no es complicado si tiene pequeños fragmentos de código.que realice la solicitud y el análisis, también verá que es tan fácil depurarlos y encontrar los problemas, quiero decir, este fue también mi caso cuando comencé a trabajar con bloques.

usando una variable de bloque

@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
}];
}

Otros consejos

Pregunté algo similar al de vuelta.Creo que encontrarás tu solución allí. bloques que pasan a un método AFnetworking?

En general, deberá cambiar la forma en que cree que debe obtener los datos de "Si está registrado, devuelva BOOL" a "Comprobar si puedo iniciar sesión, si eso falla, haga algo dentro del bloque AFNetworking.

El enlace de arriba también responde a su segunda pregunta.

Sus métodos deben tomar un bloque (o dos) que se ejecutarán desde los bloques de éxito (o falla) de AFNetworking.Este enfoque abarca la naturaleza asíncrona de lo que está tratando de hacer.No se puede agregar valores de devolución a los métodos debido a esta asincronicidad.


Entonces, cambiaría su método a:

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

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

Entonces, poca actualización sobre la situación (gracias a todas las sugerencias preciosas ... ¡gracias a los chicos!). Ahora, mi código se ve así (en mi Networkmodel.m, obviamente he agregado el método a NetworkModel.h para que pueda llamarlo en cualquier lugar):

-(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);
}];
}

en mi appdelegate.h He incluido mi nombre de red y en mi appdelegate.m Ahora tengo el siguiente código:

[[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];
    }    
}];

y funciona un poco bien. Pero ahora tengo otra pregunta sobre esto. Cuando corro la aplicación, hay algo raro sucede. Tan pronto como recupere la información sobre el estado de inicio de sesión del usuario, salta de VC (el Controlador de Comercialview designado - START00 en MI Storyboard) a VC (loggedinvc - start01 en mi guión gráfico). ¿Hay alguna forma de no mostrar este tipo de salto al usuario? ¿O esto es un comportamiento normal? Ahora el usuario ve por un segundo la primera pantalla y luego la pantalla en la que debería ver (porque ha iniciado sesión).

Pero supongo que la forma más fácil de trabajar con bloques y todo esto es usarlos justo donde los necesito. En lugar de tratar de encapsularlos en métodos o clases o lo que sea. Tan pronto como los datos están ahí, haré lo que tengo, directamente dentro del éxito del éxito o el fallo. ¿Estoy pensando bien?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top