Как сразу получить результат в блоках?

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

Я реализовал такой код

В первом классе:

- (void)viewDidLoad {
    [super viewDidLoad];
    UserAuthentication *auth = [[UserAuthentication alloc]init];
    NSDictionary *dict = [auth getUserConfiguration];
    NSLog(@"%@",dict);
}

В классе userAuthentication:

-(NSDictionary *)getUserConfiguration;
{
    __block NSDictionary *resultDictionary;
    NSURLSession *session = [NSURLSession sharedSession];
    [[session dataTaskWithURL:[NSURL URLWithString:@"http://72.52.65.142:8083/auth"]
            completionHandler:^(NSData *data,
                                NSURLResponse *response,
                                NSError *error) {
                NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
                if ([response respondsToSelector:@selector(allHeaderFields)]) {
                     resultDictionary = [httpResponse allHeaderFields];
                    NSLog(@"%@",resultDictionary);
                }
            }] resume];
    NSLog(@"%@",resultDictionary);
    return resultDictionary;
}

Здесь моя проблема в первом классе я получаю dict как ноль.

Даже в userAuthentication класс также я получаю ноль.

Но через некоторое время вызывается метод обратного вызова, и тогда я могу правильно увидеть ответ в completionHandler,

Итак, как я могу получить ответ в первом классе?

5 ответов

Решение

Вы неправильно понимаете основной принцип асинхронной операции, которая выполняется в фоновом потоке, и когда операция завершается, она предоставляет вам данные в блоке завершения.

Чтобы получить ответ в методе viewDidLoad второго класса, вам нужно использовать блоки. как ниже

-(void)getUserConfigurationOnCompletion:(void (^)(NSDictionary *))completion
{
    __block NSDictionary *resultDictionary;
    NSURLSession *session = [NSURLSession sharedSession];
    [[session dataTaskWithURL:[NSURL URLWithString:@"http://72.52.65.142:8083/auth"]
            completionHandler:^(NSData *data,
                                NSURLResponse *response,
                                NSError *error) {
                NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
                if ([response respondsToSelector:@selector(allHeaderFields)]) {
                     resultDictionary = [httpResponse allHeaderFields];
                   // Call completion with parameter
                    completion(resultDictionary);
                }
            }] resume];
}

и использовать это так в viewDidLoad

- (void)viewDidLoad {
    [super viewDidLoad];
    UserAuthentication *auth = [[UserAuthentication alloc]init];
    [auth getUserConfigurationOnCompletion:^(NSDictionary *dict){
    // do necessary work with response dictionary here
    NSLog(@"%@",dict);

   }];
}

Это то, к чему вы должны привыкнуть: все, что связано с доступом в Интернет (и некоторые вещи, не связанные с ним), не может быть возвращено немедленно - если вы не готовы ждать этого, заблокировать свой пользовательский интерфейс и сделать своих пользователей очень, очень несчастен

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

Вы используете NSURLSession! Он выполняет задачи в фоновом потоке! Блок завершения вызывается только тогда, когда вы получаете ответ от сервера. Естественно, для завершения запроса потребуется время. Вы должны использовать блоки, чтобы завершить запрос и вернуть результат по завершении.

-(void)getUserConfigurationAndOnCompletion:(void(ˆ)(NSDictionary *dict, NSError *error))completion;
{
    __block NSDictionary *resultDictionary;
    NSURLSession *session = [NSURLSession sharedSession];
    [[session dataTaskWithURL:[NSURL URLWithString:@"http://72.52.65.142:8083/auth"]
            completionHandler:^(NSData *data,
                                NSURLResponse *response,
                                NSError *error) {
                NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
                if ([response respondsToSelector:@selector(allHeaderFields)]) {
                     resultDictionary = [httpResponse allHeaderFields];
                    NSLog(@"%@",resultDictionary);

                 //This will call the block in the first class with the result dictionary

              dispatch_async(dispatch_get_main_queue(), ^{
                   if(!error){
                       completion(resultDictionary,nil);
                   }else{
                       completion(nil,error);
                   }
              });

        }] resume];
}

Когда вы вызываете приведенный выше код из вашего первого класса, он создаст там блок, и вы получите необходимый словарь там в параметре блока!

Ваш метод должен быть как,

  -(void)getUserConfigurationwithCompletionHandler : (void (^)(NSDictionary* resultDictionary))completionHandler
{
__block NSDictionary *resultDictionary;
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:@"http://72.52.65.142:8083/auth"]
        completionHandler:^(NSData *data,
                            NSURLResponse *response,
                            NSError *error) {
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
            if ([response respondsToSelector:@selector(allHeaderFields)]) {
                resultDictionary = [httpResponse allHeaderFields];
                NSLog(@"%@",resultDictionary);

                completionHandler(resultDictionary);

            }
        }] resume];
  NSLog(@"%@",resultDictionary);

}

и вы можете получить к нему доступ, как,

  - (void)viewDidLoad {
       [super viewDidLoad];

       [self getUserConfigurationwithCompletionHandler:^(NSDictionary *resultDictionary) {

    // you can acess result dictionary here

    NSLog(@"%@",resultDictionary);

    }];

 }

потому что вы будете получать данные в ответ от веб-службы (с сервера), поэтому для завершения требуется некоторое время, поэтому вам нужно возвращать данные из обработчика завершения вызова веб-службы, и вы не можете вернуть данные из обработчика завершения, поэтому вам нужно создать собственный обработчик завершения и звоните, как я уже говорил выше. вы можете получить доступ resultDictionary в completionHandler и вы можете показать новый VC из этого completionHandler,

Вы должны вызывать метод в вашем первом классе в вашем завершении.

  1. Создайте свойство типа YOURFIRSTCLASS *myfirstclass в своем классе UserAuthentication.

  2. Передайте свой первый класс с "self" объекту UserAuthentication.

  3. создать видимый метод в вашем первом классе "-(void)responseCaller:(NSDictionary)dict"

  4. вызовите метод в вашем методе ответа

YOURFIRSTCLASS.h:

-(void)responseCaller:(NSDictionary)dict;

YOURFIRSTCLASS.m

-(void)responseCaller:(NSDictionary)dict
{NSLog(@"%@",dict);}

- (void)viewDidLoad {
    [super viewDidLoad];
    UserAuthentication *auth = [[UserAuthentication alloc]init];
    auth.myfirstclass = self;
    NSDictionary *dict = [auth getUserConfiguration];
    NSLog(@"%@",dict);
}

UserAuthentication.h

#import "YOURFIRSTCLASS.h"
@property (nonatomic) *myfirstclass;

UserAuthentication.m

-(NSDictionary *)getUserConfiguration;
{
    __block NSDictionary *resultDictionary;
    NSURLSession *session = [NSURLSession sharedSession];
    __weak myfirstclassSave = myfirstclass;
    [[session dataTaskWithURL:[NSURL URLWithString:@"http://72.52.65.142:8083/auth"]
            completionHandler:^(NSData *data,
                                NSURLResponse *response,
                                NSError *error) {
                NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
                if ([response respondsToSelector:@selector(allHeaderFields)]) {
                     resultDictionary = [httpResponse allHeaderFields];
                     [myfirstclassSave responseCaller:resultDictionary ];

                }
            }] resume];

    return resultDictionary;
}

Что-то вроде того

Другие вопросы по тегам