Método delegado não chamado após descartar o controlador de visualização modal
-
21-12-2019 - |
Pergunta
estou usando NSURLSessionDataTask
para recuperar JSON de um URL no meu JsonClient
classe, esta classe possui um protocolo delegado para notificar quando a tarefa json for concluída.
JsonClient.h
#import <Foundation/Foundation.h>
@protocol JsonDelegate <NSObject>
- (void)jsonFetchComplete;
@end
@interface JsonClient : NSObject
@property (weak,nonatomic) id <JsonDelegate> delegate;
- (void)fetchJsonData;
@end
JsonClient.m
#import "JsonClient.h"
@implementation JsonClient
- (void)fetchJsonData {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSString *urlString = @"http://api.kivaws.org/v1/loans/search.json?status=fundraising";
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
//urlString = [urlString stringByAppendingString:@".json"];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:1 timeoutInterval:10];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"error: %@",error.localizedDescription);
dispatch_sync(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"ERROR"
message:error.localizedDescription
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:nil];
[alert show];
});
} else {
NSLog(@"got data");
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSError *jsonerror = nil;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonerror];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"json is \n %@",dict);
[self.delegate jsonFetchComplete];
NSLog(@"done");
});
}
}];
[task resume];
}
@end
Buscar o json funciona bem.Mas, por algum motivo, o método delegado não está sendo chamado no meu primeiro controlador de visualização. ViewController
presentes ViewController2
com uma segue modal.Um botão em ViewController2
busca o json quando tocado e descarta de volta ao primeiro ViewController
.
ViewController.m
#import "ViewController.h"
#import "JsonClient.h"
@interface ViewController () <JsonDelegate>
@property (weak,nonatomic) IBOutlet UILabel *label;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.label.text = @"Loaded VC";
}
- (void)viewWillAppear:(BOOL)animated {
NSLog(@"view will appear");
JsonClient *jc = [[JsonClient alloc] init];
jc.delegate = self;
}
// delegate method from JsonClient
- (void)jsonFetchComplete {
NSLog(@"fetch complete");
self.label.text = @"Completed!";
}
- (IBAction)toHome:(UIStoryboardSegue *)segue {
// unwind segue
}
@end
ViewController2.m
#import "ViewController2.h"
#import "JsonClient.h"
#import "ViewController.h"
@interface ViewController2 ()
@end
@implementation ViewController2
- (IBAction)getJsonData:(id)sender {
JsonClient *jsonClient = [[JsonClient alloc] init];
[jsonClient fetchJsonData];
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
Por que o método delegado está no primeiro controlador de visualização ViewController
não ligou?
Solução
A menos que JsonClient
é um Singleton, e você não está nos dizendo, você está criando duas instâncias de JsonClient
, um no viewWillAppear
método de ViewController
e outro no getJsonData
método de ViewController2
.
Essas duas instâncias rastreiam seus delegados separadamente e você está configurando apenas um deles.O segundo, aquele que é chamado quando você clica no botão ViewController2
, nunca tem seu delegado definido, então o padrão é nil
, e mensagens enviadas para nil
fazer nada.
Você precisa de algo como:
@implementation ViewController2
- (IBAction)getJsonData:(id)sender {
JsonClient *jsonClient = [[JsonClient alloc] init];
jsonClient.delegate = otherViewController;
[jsonClient fetchJsonData];
[self dismissViewControllerAnimated:YES completion:nil];
}
@end