Problems with creating a delegate

Discussion in 'iOS Programming' started by PPeelen, Aug 22, 2009.

  1. PPeelen macrumors newbie

    Joined:
    Jan 24, 2009
    #1
    Hi,

    I am trying to make a delegate, but can't really get it to work.
    This is my code for my fetchURLData.h:
    Code:
    
    #import <Foundation/Foundation.h>
    
    
    @class fetchURLData;
    @protocol fetchURLDataDelegate;
    
    @protocol fetchURLDataDelegate<NSObject>
    
    @optional
    - (void)didFinishWithData:(NSData *)fileData;
    - (void)didFailWithError:(NSError *)error;
    
    @end
    
    @interface fetchURLData : NSObject {
    	NSString *theURL;
    	NSString *theResult;
    	NSMutableData *receivedData;
    	
        long long bytesReceived;
        long long expectedBytes;
    	
        id<fetchURLDataDelegate> delegate;
    }
    
    - (NSString *) getTheURL;
    - (NSString *) getTheResult;
    
    - (void) setUrl: (NSString *) getTheURL;
    - (void) setResult: (NSString *) getTheResult;
    - (void) getData;
    
    @property (assign) id<fetchURLDataDelegate> delegate;
    
    @end
    
    and this is the code for my fetchURLData.m:
    Code:
    #import "fetchURLData.h"
    
    
    @implementation fetchURLData
    
    @synthesize delegate;
    
    - (NSString *) getTheURL
    {
    	return theURL;
    }
    
    - (NSString *) getTheResult
    {
    	return theResult;
    }
    
    - (void) setUrl: (NSString *) getTheURL
    {
    	[theURL autorelease];
    	theURL = [getTheURL retain];
    }
    
    - (void) setResult: (NSString *) getTheResult
    {
    	[theResult autorelease];
    	theResult = [getTheResult retain];
    }
    
    - (void) getData
    {	
    	NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:theURL] 
    												cachePolicy:NSURLRequestUseProtocolCachePolicy 
    											timeoutInterval:60.0];
    	
    	NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest 
    																	 delegate:self];
    	if (theConnection) 
    	{		
    		receivedData=[[NSMutableData data] retain];
    	} 
    	else 
    	{
    		UIAlertView *alert = [[UIAlertView alloc] 
    							  initWithTitle:@"Error" 
    							  message:@"An error occured while loading your request." 
    							  delegate:self 
    							  cancelButtonTitle:@"Close" 
    							  otherButtonTitles:nil];
    		[alert show];
    		[alert release];
    	}
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {	
        expectedBytes = [response expectedContentLength];
    	[receivedData setLength:0];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
    	NSLog(@"Bytes: %d of %d", [receivedData length]);
    	
    	[receivedData appendData:data];	
    }
    
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
    	if (self.delegate != NULL && [self.delegate respondsToSelector:@selector(didFailWithError:)]) {
    		[self.delegate didFailWithError:error];
    	}
    	else {
    		NSLog(@"Delegate doesn't repond to connector didFailWithError");
    	}
    	
    	[connection release];
    
    	[receivedData release];
    	// inform the user
    	NSLog(@"Connection failed! Error - %@ %@",
              [error localizedDescription],
              [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
    	if (self.delegate != NULL && [self.delegate respondsToSelector:@selector(didFinishWithData:)]) {
    		[self.delegate didFinishWithData:receivedData];
    	}
    	else {
    		NSLog(@"Delegate doesn't repond to connector didFinishWithData");
    	}
    	
        [connection release];
    	
    	NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);
    		
    	NSString *result = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
    	theResult = result;
    	
    	[receivedData release];
        [connection release];
    	[result release];
    }
    
    - (void) dealloc {
    	[theURL release];
    	[theResult release];
    	[super dealloc];
    }
    
    @end
    
    The data is retrieved but the log shows this:
    The code calling fetchURLData doesn't recieve anything:
    Code:
    
    - (void)didFinishWithData:(NSData *)fileData
    {
    	NSLog(@"Got some!");
    }
    
    - (void)didFailWithError:(NSError *)error
    {
    	NSLog(@"Got error!");
    }
    
    The log doesn't show anything

    What am I doing wrong?

    Best regards,
    Paul Peelen
     
  2. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #2
    Did you forget to set the delegate in the code that uses that class?
     
  3. PPeelen thread starter macrumors newbie

    Joined:
    Jan 24, 2009
    #3
    Well... off course I forgot that as well. I added it, but it still issn't working:

    This is the calling class "searchResults.h":
    Code:
    #import <UIKit/UIKit.h>
    #import "fetchURLData.h"
    
    @interface searchResults : UIViewController <fetchURLDataDelegate> {
    	IBOutlet UIActivityIndicatorView *loadingIndicator;
    	IBOutlet UIProgressView *progressView;
    	IBOutlet UILabel *searchingText;
    }
    
    @property (nonatomic, retain) IBOutlet UIActivityIndicatorView *loadingIndicator;
    @property (nonatomic, retain) IBOutlet UIProgressView *progressView;
    @property (nonatomic, retain) IBOutlet UILabel *searchingText;
    
    @end
    
    and the code "searchResults.m":
    Code:
    
    #import "searchResults.h"
    
    @implementation searchResults
    
    @synthesize loadingIndicator;
    @synthesize progressView;
    @synthesize searchingText;
    
    - (void)viewDidLoad {
    	[self setTitle:@"Search results"];
    	
    	fetchURLData *fetchURL = [[fetchURLData alloc] autorelease];
    	[fetchURL setUrl:@"http://www.google.com"];
    	[fetchURL getData];
    	
    	NSLog(@"The result of my class is: %@", [fetchURL getTheResult]);
    	
    	[super viewDidLoad];
    }
    
    - (void)didFinishWithData:(NSData *)fileData
    {
    	NSLog(@"Got some!");
    }
    
    - (void)didFailWithError:(NSError *)error
    {
    	NSLog(@"Got error!");
    }
    
    - (void)didReceiveMemoryWarning {
    	// Releases the view if it doesn't have a superview.
        [super didReceiveMemoryWarning];
    	
    	// Release any cached data, images, etc that aren't in use.
    }
    
    - (void)viewDidUnload {
    	// Release any retained subviews of the main view.
    	// e.g. self.myOutlet = nil;
    }
    
    
    - (void)dealloc {
        [super dealloc];
    }
    
    
    @end
    
    I still have no clue
     
  4. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #4
    I still don't see you setting the delegate of fetchURL to anything. Where is the
    Code:
    fetchURL.delegate = <whatever>
    
    or

    Code:
    [fetchURL setDelegate:<whatever>];
    
    Simply calling alloc/init does not set the instance creating the object as the delegate.
     
  5. PPeelen thread starter macrumors newbie

    Joined:
    Jan 24, 2009
    #5
    That makes sence... I am going to google how to use that. I am quite new to Objective-C and (as you might noticed... ) delegates.

    Please do give me some good links on delegate tutorials if you have any.

    Regards,
    Paul Peelen
     
  6. HerQ macrumors newbie

    Joined:
    Jun 11, 2008
    Location:
    The Netherlands
    #6
    Delegates are actually pretty straight forward once you know how they should be used. Cocoa makes heavily use of the delegation pattern as you may have noticed. An object may have a delegate to perform some methods on the delegate object to let that object know about the state the other object is in. It may also ask the delegate object whether it should perform some action or not, or it may ask the delegate for some data the other object need.

    Setting the delegate of fetchURLData to the searchResults object, the delegate property of fetchURLData will now point to the searchResults object so the searchResults object will be receiving all the delegate actions performed by the fetchURLData object.

    Another problem you have now is in the creation of the fetchURLData class. You do not call -init after -alloc, so your object won't be initialized. Try the following:
    Code:
    fetchURLData *fetchURL = [[[fetchURLData alloc] init] autorelease];
    And just like you have set the delegate to be a property of fetchURLData, you can set theResult and theURL as properties, so you don't have to define those setTheResults: methods etc. Read the Apple Documentation for more info about this subject. Good practice is not to use the 'get' prefix within get methods, the Cocoa standard just uses the variable's name itself as method name of the getter.

    Good luck!
     
  7. PPeelen thread starter macrumors newbie

    Joined:
    Jan 24, 2009
    #7
    Thanks alot for your info. Earlier I tried the following code, and it worked perfect:
    Code:
    	fetchURL = [[fetchURLData alloc] autorelease];
    	[fetchURL setDelegate:self];
    
    I will change it with the -init part. I will most likely need to change some stuff cause I need to get data from 3 urls.
    First I need to call the server, retrieve a new URL.
    Then I need to call that URL and retrieve the data.
    Then I need to send this data to the server for processing and retrieve a XML file with the result. So I have quite some things left to do.

    Thank you all very much for your help!

    Regards,
    Paul Peelen
     

Share This Page