如何立即得到块中的结果?

How to get result in blocks immediately?

我正在使用块从一个 class 中的响应中获取 header 字段,我必须在另一个 class 中获取它。

我实现了这样的代码

第一个class:

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

在用户身份验证中 class:

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

我的问题首先出现在 class 我得到的 dict 为空。

即使在 userAuthentication class 中我也得到空值。

但一段时间后回调方法正在调用,然后我可以在 completionHandler 中正确看到响应。

那么我怎样才能在 firstClass 中得到回应?

您正在使用 NSURLSession!它在后台线程上执行任务! 仅当您从服务器获得响应时才会调用完成块。完成请求自然需要时间。您应该使用块来完成请求并 return 完成时的结果。

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

当您从第一个 class 调用上述代码时,它将在那里创建一个块,您将在块参数中获得所需的字典!

你的方法应该是这样的,

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

    }];

 }

因为您将(从服务器)获取响应 web 服务的数据,所以需要一些时间才能完成,所以您必须 return 来自 web 服务调用的完成处理程序的数据,而您不能 return 来自完成处理程序的数据,因此您必须创建自己的完成处理程序并调用我上面提到的。您可以在 completionHandler 中访问 resultDictionary,并且您可以从这个 completionHandler 中显示新的 VC。

您误解了在后台线程中运行的异步操作的基本原理,当操作完成时它会在完成块中为您提供数据。

要在第二个 class 的 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);

   }];
}

这是你必须习惯的事情:任何与互联网访问相关的东西(以及一些与之无关的东西)都不能立即返回 - 除非你愿意等待它,否则阻止你的用户界面,并让您的用户非常非常不高兴。

你必须以这样一种方式编写你的应用程序,它可以处于四种状态:从未请求用户配置、请求用户配置、已请求并收到用户配置或已请求用户配置失败。在这种情况下,您的视图必须处理所有四种可能性,并且必须在情况发生变化时处理。

您必须在 completionHandler 的第一个 class 中调用一个方法。

  1. 在您的 UserAuthentication Class 中创建类型为 YOURFIRSTCLASS *myfirstclass 的 属性。

  2. 将您的第一个 class 和 "self" 传递给 UserAuthentication 对象。

  3. 在你的第一个class中创建可见方法“-(void)responseCaller:(NSDictionary)dict”

  4. 调用响应方法中的方法

你的第一堂课.h:

-(void)responseCaller:(NSDictionary)dict;

你的第一堂课.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);
}

用户身份验证.h

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

用户身份验证.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;
}

类似的东西