I am using NSURLSessionDataTask
to retrieve JSON from a url in my JsonClient
class, this class has a delegate protocol to notify when the json task is complete.
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
Fetching the json works fine. But for some reason the delegate method is not getting called in my first view controller. ViewController
presents ViewController2
with a modal segue. A button in ViewController2
fetches the json when tapped and dismisses back to the first 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
Why is the delegate method in the first view controller ViewController
not called?
Unless JsonClient
is a Singleton, and you're not telling us, you're creating two instances of JsonClient
, one in the viewWillAppear
method of ViewController
and another in the getJsonData
method of ViewController2
.
These two instances track their delegates separately, and you're only setting one of them. The second one, the one that gets called when you click the button in ViewController2
, never has its delegate set, so it defaults to nil
, and messages sent to nil
do nothing.
You need something like:
@implementation ViewController2
- (IBAction)getJsonData:(id)sender {
JsonClient *jsonClient = [[JsonClient alloc] init];
jsonClient.delegate = otherViewController;
[jsonClient fetchJsonData];
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.