Как сразу получить результат в блоках?
Я использую блоки, чтобы получить поля заголовка из ответа в одном классе, и я должен получить это в другом классе.
Я реализовал такой код
В первом классе:
- (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
,
Вы должны вызывать метод в вашем первом классе в вашем завершении.
Создайте свойство типа YOURFIRSTCLASS *myfirstclass в своем классе UserAuthentication.
Передайте свой первый класс с "self" объекту UserAuthentication.
создать видимый метод в вашем первом классе "-(void)responseCaller:(NSDictionary)dict"
вызовите метод в вашем методе ответа
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;
}
Что-то вроде того