1

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?

wigging
  • 8,492
  • 12
  • 75
  • 117

1 Answers1

1

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
godel9
  • 7,340
  • 1
  • 33
  • 53
  • How do I grab the instance of the first view controller `ViewController` in the modally presented `ViewController2`? – wigging Nov 17 '13 at 22:08
  • 1
    @Gavin Just create a weak property of type `ViewController` in `ViewController2` and set that in `prepareForSegue:sender:` method of the `ViewController` with `self`, as you are using a storyboard. – Ayan Sengupta Nov 17 '13 at 22:13
  • Making `JsonClient` a singleton fixed my problem by ensuring I'm always referring to the same instance of `JsonClient`. Thank you for pointing that out. – wigging Nov 17 '13 at 22:29