views:

3152

answers:

2

Ok, I'm programming in objective-C and using Xcode. I have read through the documentation on Apple's website and understand what delegate's are but when I come to the part where it talks about how to actually implement delegate methods into code, I just become confused, especially when they say something like "now implement the delegate's method." Maybe it's just me, but I don't know exactly WHERE to implement the method (would the AppDelegate.h/.m file be the correct location in a simple situation where I only have the ViewController and AppDelegate class?). I guess truly the best way for me to learn is to see a very simple example.

I've got some code below and I was wondering if someone could go through and show me how to connect the delegate to the ViewController so that it shows the sum? Sorry if the code looks long, but this is the simplest delegation example I could think of. For the sake of argument and having less code to look at (making it easier for me to see what's happening), lets say ServerClass *server implements a server and ClientClass *client implements a client. Both are already connected to each other and are waiting to input their number. I put down what I think would be correct but I know for sure it's not complete (as far as connecting the delegate to both server and client). One thing I don't know where to put are the protocol declarations, so if someone could please do this simple problem, it would help me out a lot as far as learning how a delegate is implemented into a class.

By the way, I'm working with the Peer Picker in the new GameKit of the iPhone SDK 3.0 if someone would also like to show me what connects to what. For example, I am at step 3 of the Apple guide for Peer Picker. Now, I don't know where step 5 goes in my project. Thanks to all who can help me understand this delegate implementation...you all have been great so far!

ExampleAppDelegate.h

#import <UIKit/UIKit.h>

@class ExampleAppViewController;

@interface ExampleAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    ExampleAppViewController *viewController;
    int sum;
}

@property (nonatomic, retain) sum;
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet ExampleAppViewController *viewController;

-(void) addNum:(int)num;
@end

ExampleAppDelegate.m

#import "ExampleAppDelegate.h"
#import "ExampleAppViewController.h"

@implementation ExampleAppDelegate

@synthesize window;
@synthesize viewController;


- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    application.idleTimerDisabled = YES;

    // Override point for customization after app launch    
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
}


- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}

-(void)addNum:(int)num {
    sum += num;
}

@end

ExampleAppViewController.h

#import <UIKit/UIKit.h>
#import <GameKit/GameKit.h>

@interface ExampleAppViewcontroller : NSObject {
        IBOutlet UILabel *sumField; // will display the total sum, one number entered //by the server and one entered by the client, on both iPhones after calculation

        int sum; // the total sum after addition;
        ServerClass *server; // some server
        ClientClass *client; // some client
        int num; // the number to add to sum
}

@property(nonatomic, assign) sum;
@property(nonatomic, retain) num;

-(void) displaySum;
@end

ExampleAppViewController.m

#import "ExampleAppViewcontroller.h"

@implementation ExampleAppViewController

@synthesize sum;
@synthesize num;

-(void) displaySum {
    [sumfield setText: @"%i", sum];
}

@end
+2  A: 

I won't go into any detailed analysis of the code you posted — the most helpful response you could get is some direction as far as general principles that transcend a specific code sample. Here are the general principles...

  • A delegate is an object whose objects are (generally) called to handle or respond to specific events or actions.
  • You must "tell" an object which accepts a delegate that you want to be the delegate. This is done by calling [object setDelegate:self]; or setting object.delegate = self; in your code.
  • The object acting as the delegate should implement the specified delegate methods. The object often defines methods either in a protocol, or on NSObject via a category as default/empty methods, or both. (The formal protocol approach is probably cleaner, especially now that Objective-C 2.0 supports optional protocol methods.)
  • When a relevant event occurs, the calling object checks to see if the delegate implements the matching method (using -respondsToSelector:) and calls that method if it does. The delegate then has control to do whatever it must to respond before returning control to the caller.

In the specific example you're working through, notice that GKPeerPickerController has a property named delegate which accepts an object of type id<GKPeerPickerControllerDelegate>. This means an id (any subclass of NSObject) that implements the methods in the GKPeerPickerControllerDelegate protocol. GKPeerPickerControllerDelegate in turn defines a number of delegate methods and describes when they will be called. If you implement one or more of those methods (the documentation says all are optional, but two are expected) and register as a delegate, those methods will be called. (Note that you don't need to declare a method prototype in your .h file, just import the protocol header and implement the method in your .m file.

Quinn Taylor
Thanks for your help. I now understand delegation a lot better.
Josh Bradley
+1  A: 

I am learning ObjC and iPhone development. I wouldn't reach so far up as to say that I understand delegates and their use perfectly. Your First iPhone Application, found on the developer portal on Apple site, walks through in detail a very simple example that makes use of the TextField's delegate to override a method to make the keyboard disappear when editing on the TextField is done. For example, if I can paste relevant snippets from there:

// MyViewController.h
#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController <UITextFieldDelegate> {
        UITextField *textField;
        UILabel *label;
        NSString *string;
}

@property (nonatomic, retain) IBOutlet UITextField *textField;
@property (nonatomic, retain) IBOutlet UILabel *label;
@property (nonatomic, copy) IBOutlet NSString *string;

- (IBAction)changeGreeting:(id)sender;

@end


// MyViewController.m
#import "MyViewController.h"

@implementation MyViewController

@synthesize textField;
@synthesize label;
@synthesize string;

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
        if (theTextField == textField) {
                [textField resignFirstResponder];
        }
        return YES;
}

@end

Over here, textFieldShouldReturn is a method that is part of the UITextFieldDelegate protocol. As much as I have understood it, what is important is that whichever class you implement the delegate methods in, that class must follow that particular delegate's protocol (by having a protocol name enclosed in angle brackets immediately next to the name of the class it inherits from).

ayaz
This cleared things up a lot about where and how to include the delegate protocols. One question though, After the protocol has been set (in the angle brackets in the .h file) and I have declared the delegate (i.e picker.delegate = self), does this mean that picker now has inherited all the protocol methods or do I need to add some other line of code that does this before I start using the protocol methods with picker?
Josh Bradley
As far as I understand, if a class follows a delegate protocol, it can override all the methods that are defined by the delegate protocol.
ayaz
When you adopt a protocol (whether it's for a delegate or anything else) you don't "inherit" any variables or method implementations. (That only occurs when you extend a parent class, such as UIViewController or NSObject.) A protocol is like a Java interface: adopting a protocol is a promise that you will implement (at least the required) methods it declares. Protocols are used to establish formal expectations of what a caller may ask instances of your object to do, and by default the compiler will warn you of unimplemented required protocol methods.
Quinn Taylor