views:

5672

answers:

6

I am building a class that handles NSURLConnection requests. To allow other classes to use this class, I would like to allow the main class to call a delegate when connectionDidFinishLoading is fired.

I've looked through lots of documentation, but I can't find anything that gives any clear examples, and the code that I have doesn't call the delegate for some reason. The code I have so far is (code not relevant removed):

Interface:

@interface PDUrlHandler : NSObject {
id delegate;
}
- (void)searchForItemNamed:(NSString *)searchQuery;
@property (nonatomic, assign) id delegate;
@end
@interface NSObject (PDUrlHandlerDelegate) 
- (void)urlHandler:(PDUrlhandler*)urlHandler searchResultsFinishedLoading:(NSDictionary *)resultData;
@end

Implementation:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSLog(@"Fininshed Loading...");
    resultData = [self parseJSON:jsonData];

    if(delegate && [delegate respondsToSelector:@selector(urlHandler:searchResultsFinishedLoading:)]) {
     NSLog(@"Delegating!");
     [delegate urlHandler:self searchResultsFinishedLoading:resultData];
    } else {
     NSLog(@"Not Delegating. I dont know why.");
    } 

}

The delegate within the other class:

- (void)urlHandler:(PDUrlhandler*)urlHandler searchResultsFinishedLoading:(NSDictionary *)resultData;
{
    NSLog(@"Delegating!!!!");
}
+1  A: 

You're on the right track, the way you're implementing the delegate pattern looks okay. The reason it's not being called is because you're using the wrong method signature in respondsToSelector; you have humidorServer:searchResultsFinishedLoading: when you actually want urlHandler:searchResultsFinishedLoading:.

Marc Charbonneau
A: 

Could it be the semi colon at the end of the method name in the delegate (bottom code sample on the far right)? If the delegate is set and the -connectionDidFinishLoading: method is being called then I can't see anything wrong

Martin Pilkington
Leaving a semicolon on a method name in the implementation is valid in Objective-C. I like to do it as habit because you can copy and paste between the implementation and interface without worrying about it.
Marc Charbonneau
+1  A: 

Turns out I forgot to set the delegate:

[currentHandler setDelegate:self];

needed to go after the line that makes the initial call to the PDUrlHandler.

pixel
+4  A: 

My first thought was you might not have set the delegate, but you have. Other than that, the code looks correct. Can't see anything wrong. Did you try and put a breakpoint at the place where you are checking whether your delegate responds to a selector? Could be that the delegate value was not retained and became nil. Make sure your delegate is not nil and has the correct object.

Also are you sure the connection is asynchronous? Synchronous connections will not call the connectionDidFinishLoading method

lostInTransit
A: 

Since you tagged this with "iphone", I assume you're working on an iPhone app and don't need to support OS X pre-10.5. In Objective-C 2.0, Apple suggests you use formal protocols (using @protocol) with optional methods instead of informal protocols. Here's the relevant text:

Being informal, protocols declared in categories don’t receive much language support. There’s no type checking at compile time nor a check at runtime to see whether an object conforms to the protocol. To get these benefits, you must use a formal protocol. An informal protocol may be useful when all the methods are optional, such as for a delegate, but (on Mac OS X v10.5 and later) it is typically better to use a formal protocol with optional methods.

(source)

Martin Gordon
+2  A: 

For anyone interested in seeing an example of this the apple sample application NSURLCache implements a simple delegate around an NSURLConnection in NSURLCacheConnection.m

The sample app is available through the apple developer connection here: http://developer.apple.com/iphone/library/samplecode/URLCache/index.html

I found it pretty useful.

paulthenerd