0

So, I'm following this answer in trying to pass data between two classes in an iOS project without storyboards. I'm trying to abstract all my server calls in a different class, so the ViewControllers don't get too cramped. I have an OfferRequest class, which handles the server requests and declares the protocol:

@protocol OfferRequestDelegate <NSObject>

-(void)addOfferRequest: (OfferRequest *)request dataFromRequest: (NSMutableArray *)data;

@end

@interface OfferRequest : NSObject <LocationManagerDelegate, NSURLConnectionDataDelegate>

@property (nonatomic, weak) id <OfferRequestDelegate> delegate;
@end

The idea is to call addOfferRequest: dataFromRequest in connectionDidFinishLoading, set the data as the result from the request and pass it on to the ViewController.

In OfferRequest.m:

-(void)connectionDidFinishLoading:(NSURLConnection *)connection {

    NSMutableArray *result = [NSJSONSerialization JSONObjectWithData:receivedData options:kNilOptions error:nil];
    [self.delegate addOfferRequest:self dataFromRequest:result];

}

I declare my ViewController as a delegate for the OfferRequest:

@interface CategorySuggestionViewController : UIViewController <OfferRequestDelegate>

Initialize the OfferRequest object and set it's delegate:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    offer = [OfferRequest new];
    offer.delegate = self;
}

And then implement the delegate method:

-(void)addOfferRequest:(OfferRequest *)request dataFromRequest:(NSMutableArray *)data {
    NSLog(@"received data = %@", data);
}

But it never gets called. What am I missing ?

Community
  • 1
  • 1
smeshko
  • 1,184
  • 13
  • 27
  • Does your connectionDidFinishLoading method get called? – Rukshan Dec 09 '14 at 10:26
  • Could you paste the code with the the creation of connection and the request for that connection? -Off topic- Maybe you should consider using blocks. – Adi Pop Dec 09 '14 at 10:27
  • Yes, it gets called and the data is correctly set. – smeshko Dec 09 '14 at 10:28
  • @AdiPop I don't think it is relevant, since the data in OfferRequest is correctly set. Also: could you please point me to an explanation how to use blocks in this situation ? I'm not very experienced with objective c. – smeshko Dec 09 '14 at 10:30
  • 3
    Did you check inside connectionDidFinishLoading if delegate is not nil ? – Adi Pop Dec 09 '14 at 10:31
  • @AdiPop Hm, yes, it is nil. I have `@synthesize delegate;` at the beginning of `OfferRequset.m` and I thought it gets initialized there. How and where should I initialize it ? – smeshko Dec 09 '14 at 10:34
  • 1
    @smeshko Are you allocating offer in any other place apart from viewDidLoad? – thavasidurai Dec 09 '14 at 10:40
  • @thavasidurai No, `offer` is a property that I use throughout the ViewController, I don't need any other `OfferRequest` instances. The weird thing is, I call the `OfferRequest` method in `didSelectRowAtIndexPath` and set the delegate in `viewDidLoad`, so you'd expect, that the delegate is set before it is needed in `OfferRequest`. Or am I seeing it wrong ? – smeshko Dec 09 '14 at 10:42
  • 1
    initiliaze your offer =[[OfferRequest alloc]init]; instead of offer = [OfferRequest new] – karthikeyan Dec 09 '14 at 10:44
  • @karthikeyan Still doesn't work: `delegate` is still Nil in `connectionDidFinishLoading` and the delegate method doesn't get called. – smeshko Dec 09 '14 at 10:46
  • @smeshko if possible can you please post code which you wrote in didSelectRowAtIndexPath? – thavasidurai Dec 09 '14 at 10:48
  • if connectionDidFinishLoading get called,check your result array whether having value or not – karthikeyan Dec 09 '14 at 10:49
  • I think that the instance of CategorySuggestionViewController is deallocated that will explain that the delegate is nil. – Adi Pop Dec 09 '14 at 12:14
  • In how many different places do you create an OfferRequest? – Hot Licks Dec 09 '14 at 13:11

3 Answers3

0

try this...

your OfferRequest class like below i have given name it as connectionClass

connectionClass.h

@protocol connectionDelegate <NSObject>
-(void)connectionSucceed:(NSData *)data;
-(void)connectionFailed:(NSError *)error;
@end

#import <Foundation/Foundation.h>

@interface connectionClass : NSObject
{
    id<connectionDelegate> delegate;
    NSMutableData *receivedData;
    NSString *encodedString;
    NSMutableURLRequest *theRequest;
    NSURL *url;
    NSString *length;
    NSURLConnection *Connect;

}
@property(nonatomic, retain) id<connectionDelegate> delegate;
@property(nonatomic, retain) NSMutableData *receivedData;
- (void)connectionWithURL:(NSString *)URL;
@end

connectionClass.m

#import "connectionClass.h"

@implementation connectionClass
@synthesize delegate, receivedData;
- (void)connectionWithURL:(NSString *)URL
{
    url=[[NSURL alloc] initWithString:[self urlencode:URL]];
    theRequest= [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60];
    [theRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    length = [NSString stringWithFormat:@"%lu", (unsigned long)[URL length]];
    [theRequest setValue:length forHTTPHeaderField:@"Content-Length"];
    [theRequest setHTTPMethod:@"POST"];

    [theRequest setHTTPBody:[URL dataUsingEncoding:NSUTF8StringEncoding]];

    Connect = [NSURLConnection connectionWithRequest:theRequest delegate:self];

    if (Connect)
    {
        self.receivedData = [NSMutableData data];
    }
    else
    {
        NSError *error;
        [self.delegate connectionFailed:error];
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    [self.receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.receivedData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [self.delegate connectionSucceed:self.receivedData];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    [self.delegate connectionFailed:error];
}
-(NSString *) urlencode: (NSString *) string
{
    encodedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)string, NULL, (CFStringRef)@"", kCFStringEncodingUTF16));
    return encodedString;
}


@end

don't forget to import your connectionclass and delegate

@interface yourclass : UIViewController<connectionDelegate>

Initialize the OfferRequest object and set it's delegate:

-(void)viewWillAppear:(BOOL)animated
{
    connection = [[connectionClass alloc]init];
    connection.delegate = self;
     [connection connectionWithURL:[NSString stringWithFormat:@"pass your url here"]];
}

The delegate method will have your values

-(void)connectionSucceed:(NSData *)data
{
    NSError *error;
    self.dictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
    //nslog your data
}

//Connection failure
-(void)connectionFailed:(NSError *)error
{
  //handle error message
}
karthikeyan
  • 3,821
  • 3
  • 22
  • 45
0

Ok, I don't know where the problem exactly was, but what I did to fix it, was to create a new init method, where I pass the delegate:

-(instancetype)initWithDelegate: (id<OfferRequestDelegate>) delegate {
    self = [super init];

    if (self) {
        self.delegate = delegate;
    }

    return self;
}

So I initialize the OfferRequest object in the VC and pass self and now it works.

smeshko
  • 1,184
  • 13
  • 27
-2

I guess delegate should be a pointer object and not the object.

It may be help you

@property (nonatomic, weak) NSObject <OfferRequestDelegate> *delegate;

and make should your delegate is been set, i.e. make sure your code below is getting called.

 [self.delegate addOfferRequest:self dataFromRequest:result];
karthikeyan
  • 3,821
  • 3
  • 22
  • 45
Rajesh
  • 546
  • 9
  • 29