Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create my own delegate (user defined delegate in Objective-C) [duplicate]

On iOS, how do I create a delegate (user defined)?

like image 704
Vipin_iOSdev Avatar asked Apr 14 '11 09:04

Vipin_iOSdev


People also ask

How do I create a custom delegate in Objective-C?

To create one, you define a class that implements the delegate methods you're interested in, and mark that class as implementing the delegate protocol. Then you could create an instance of MyClass and assign it as the web view's delegate: MyClass *instanceOfMyClass = [[MyClass alloc] init]; myWebView.

How do delegates work in Objective-C?

A delegate is an object that acts on behalf of, or in coordination with, another object when that object encounters an event in a program. The delegating object is often a responder object—that is, an object inheriting from NSResponder in AppKit or UIResponder in UIKit—that is responding to a user event.

Can a class have multiple delegates?

The delegate pattern is about a 1 to 1 relationship between a class and it's delegate. Whilst it is possible to achieve some level of multiple delegation through switching the delegates in and out, it's more likely to lead to unpredictable behaviour and bugs.

What does tableView delegate self mean?

Here, tableView acts as Delegator(sender) & viewController object i.e (self) as Delegate(receiver). In order to get UITableView in viewController . It should to conform to both the Protocols. So, viewController class object has implemented all those required functions of both the protocols.


2 Answers

First define a declare a delegate like this -

@protocol IconDownloaderDelegate;

Then create a delegate object like this -

@interface IconDownloader : NSObject
{
    NSIndexPath *indexPathInTableView;
    id <IconDownloaderDelegate> delegate;
    NSMutableData *activeDownload;
    NSURLConnection *imageConnection;
}

Declare a property for it -

@property (nonatomic, assign) id <IconDownloaderDelegate> delegate;

Define it -

@protocol IconDownloaderDelegate 

- (void)appImageDidLoad:(NSIndexPath *)indexPath;

@end

Then you can call methods on this delegate -

[delegate appImageDidLoad:self.indexPathInTableView];

Here is the complete source code of the image downloader class -

.h file -

@class AppRecord;
@class RootViewController;

@protocol IconDownloaderDelegate;

@interface IconDownloader : NSObject
{
    AppRecord *appRecord;
    NSIndexPath *indexPathInTableView;
    id <IconDownloaderDelegate> delegate;

    NSMutableData *activeDownload;
    NSURLConnection *imageConnection;
}

@property (nonatomic, retain) AppRecord *appRecord;
@property (nonatomic, retain) NSIndexPath *indexPathInTableView;
@property (nonatomic, assign) id <IconDownloaderDelegate> delegate;

@property (nonatomic, retain) NSMutableData *activeDownload;
@property (nonatomic, retain) NSURLConnection *imageConnection;

- (void)startDownload;
- (void)cancelDownload;

@end

@protocol IconDownloaderDelegate 

- (void)appImageDidLoad:(NSIndexPath *)indexPath;

@end

.m file -

#import "IconDownloader.h"
#import "MixtapeInfo.h"

#define kAppIconHeight 48
#define TMP NSTemporaryDirectory()

@implementation IconDownloader

@synthesize appRecord;
@synthesize indexPathInTableView;
@synthesize delegate;
@synthesize activeDownload;
@synthesize imageConnection;

#pragma mark

- (void)dealloc
{
    [appRecord release];
    [indexPathInTableView release];

    [activeDownload release];

    [imageConnection cancel];
    [imageConnection release];

    [super dealloc];
}

- (void)startDownload
{
    self.activeDownload = [NSMutableData data];

    // alloc+init and start an NSURLConnection; release on completion/failure
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:
                             [NSURLRequest requestWithURL:
                              [NSURL URLWithString:appRecord.mixtape_image]] delegate:self];
    self.imageConnection = conn;
    [conn release];

}

- (void)cancelDownload
{
    [self.imageConnection cancel];
    self.imageConnection = nil;
    self.activeDownload = nil;
}


#pragma mark -
#pragma mark Download support (NSURLConnectionDelegate)

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

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    // Clear the activeDownload property to allow later attempts
    self.activeDownload = nil;

    // Release the connection now that it's finished
    self.imageConnection = nil;
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{   
    // Set appIcon and clear temporary data/image
    UIImage *image = [[UIImage alloc] initWithData:self.activeDownload];
    self.appRecord.mixtape_image_obj = image;

    self.activeDownload = nil;
    [image release];

    // Release the connection now that it's finished
    self.imageConnection = nil;

    // call our delegate and tell it that our icon is ready for display
    [delegate appImageDidLoad:self.indexPathInTableView];
}

@end

and here is how we use it -

#import "IconDownloader.h"

@interface RootViewController : UITableViewController <UIScrollViewDelegate, IconDownloaderDelegate>
{
    NSArray *entries;   // the main data model for our UITableView
    NSMutableDictionary *imageDownloadsInProgress;  // the set of IconDownloader objects for each app
}

in .m file -

- (void)startIconDownload:(AppRecord *)appRecord forIndexPath:(NSIndexPath *)indexPath
{
    IconDownloader *iconDownloader = [imageDownloadsInProgress objectForKey:indexPath];
    if (iconDownloader == nil) 
    {
        iconDownloader = [[IconDownloader alloc] init];
        iconDownloader.appRecord = appRecord;
        iconDownloader.indexPathInTableView = indexPath;
        iconDownloader.delegate = self;
        [imageDownloadsInProgress setObject:iconDownloader forKey:indexPath];
        [iconDownloader startDownload];
        [iconDownloader release];   
    }
}

here is delegate gets called automatically -

// called by our ImageDownloader when an icon is ready to be displayed
- (void)appImageDidLoad:(NSIndexPath *)indexPath
{
    IconDownloader *iconDownloader = [imageDownloadsInProgress objectForKey:indexPath];
    if (iconDownloader != nil)
    {
        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:iconDownloader.indexPathInTableView];

        // Display the newly loaded image
        cell.imageView.image = iconDownloader.appRecord.appIcon;
    }
}
like image 124
Saurabh Avatar answered Nov 05 '22 01:11

Saurabh


This is basic concepts to create a own delegate

Delegates are very useful to control transfer within the array of view controllers in app manually. Using delegates you can manage the control flow very well.

here is small example of own delegates....

  1. Create a protocol class.... (.h only)

SampleDelegate.h

#import


@protocol SampleDelegate
@optional

#pragma Home Delegate

-(NSString *)getViewName;

@end
  1. Import above protocol class in the class whom you want to make delegate of another class. Here in my ex. I m using AppDelegate to make delegate of The HomeViewController's Object.

also add above DelegateName in Delegate Reference < >

ownDelegateAppDelegate.h

#import "SampleDelegate.h"

@interface ownDelegateAppDelegate : NSObject <UIApplicationDelegate, SampleDelegate> {

}

ownDelegateAppDelegate.m

//setDelegate of the HomeViewController's object as
[homeViewControllerObject setDelegate:self];

//add this delegate method definition
-(NSString *)getViewName
{
    return @"Delegate Called";
}

HomeViewController.h

#import
#import "SampleDelegate.h"

@interface HomeViewController : UIViewController {

    id<SampleDelegate>delegate;
}

@property(readwrite , assign) id<SampleDelegate>delegate;

@end

HomeViewController.h

- (void)viewDidAppear:(BOOL)animated {

    [super viewDidAppear:animated];


    UILabel *lblTitle = [[UILabel alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    lblTitle.text = [delegate getViewName];
    lblTitle.textAlignment = UITextAlignmentCenter;
    [self.view addSubview:lblTitle];
}
like image 21
iCrazyDev Avatar answered Nov 05 '22 00:11

iCrazyDev