Вопрос

У меня есть вопрос. Может быть, 2 вопроса.

Первый относится к этому листу кода:

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

Я хотел бы, чтобы этот метод не является пустотой, я хотел бы, чтобы он возвращал лол или то, что я могу использовать как: пользователь вошел в систему> ОК, сделайте что-то где-то в приложении; Пользователь не вошел в систему> OK Подскажите пользователю экрану, где он может представить свои учетные данные и войти в систему.

Второй вопрос связан с этим кусочком кода:

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

Я хотел бы, что этот метод возвращает мне Nsarray с анавровным JSON, который я могу использовать везде, где я хочу.

Это методы содержатся в модели под названием NetworkModel (подкласс NSObject). Мне просто интересно, почему я должен делать все внутри блоков. У меня должны быть части, взаимодействующие с сетью повсюду, и не организованы в одном уникальном месте / классе. Есть способ сделать это. Я не хочу иметь 5 строк запросов каждого ViewController. Я хочу определить методы, которые я могу позвонить с любого ViewController (очевидно, импортируя файлы заголовка, где это необходимо).

Любые предложения? Спасибо по совету!

Это было полезно?

Решение

Вы можете сделать это с 2 подходами, один изменить ваши методы, чтобы использовать блоки или использовать семафор, чтобы ждать async-запроса:

с семафором (уродливый путь)

-(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;
}
.

правильный способ сделать это

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

Для вашего второго вопроса вы можете установить переменную блока в вашем классе сети, который будет вызываться, когда запрос завершен или не удается.

В любом случае, я думаю, вы не совсем знакомы с блоками (из-за вашего второго вопроса), и я думаю, что после нескольких блоков вы начните их, и вы увидите, что код не сложно, если у вас есть небольшие фрагменты кодакоторые выполняют запрос и анализ, также вы увидите, что это оооочень легко отладить их и находить проблемы, я имею в виду, это был также мой случай, когда я начал работать с блоками.

<Сильные> Использование блочной переменной

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

Другие советы

Я спросил что-то похожее некоторое время назад.Я верю, что вы найдете там ваше решение. Передача блоков к методу Afnetworking?

В общем, вам нужно будет изменить способ, которым вы думаете, что вы должны получить данные «Если вы зарегистрированы в обратном bool», чтобы «проверить, смогу ли я войти в систему, если это не выполнит что-то в рамках блока AFNetWorking.

.

Ссылка выше также отвечает на ваш второй вопрос.

Ваши методы должны принимать блок (или два), которые будут выполняться из блоков AfnetWorking Success (или отказа).Этот подход охватывает асинхронную природу того, что вы пытаетесь сделать.Вы не можете добавить возвратные значения методам из-за этой асинхроники.


Итак, вы измените ваш метод:

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

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

Так, мало обновления по ситуации (спасибо всем драгоценным предложениям .. спасибо, ребята!). Теперь мой код выглядит так (в моей сети Model.m, очевидно, я добавил метод для NetworkModel.h, чтобы я мог нигде позвонить):

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

В моем appdelegate.h Я включил мою сетьModel.h и в моем AppDelegate.m Теперь у меня есть следующий код:

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

И это работает хорошо. Но теперь у меня есть другой вопрос об этом. Когда я запускаю приложение, происходит что-то странное. Как только он извлекает информацию о состоянии входа в систему пользователя, он переходит от VC (обозначенный контроллер ININITATIONVIEW - Start00 на мою раскадровку) в VC (logugedInvc - start01 на моей раскащенной доске). Есть ли способ не показывать эту рода прыгать к пользователю? Или это нормальное поведение? Теперь пользователь видит на второй первый экран, а затем экран он должен на самом деле увидеть (потому что он вошел в систему).

Но я думаю, самый простой способ работать с блоками, и все это нужно использовать их прямо там, где они нуждаются в них. Вместо того, чтобы пытаться заключить их в методы или классы или что-то еще. Как только данные там, я сделаю то, что у меня есть, непосредственно внутри блока успеха или неудача. Я думаю, правильно?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top