7stud
7stud

Reputation: 48599

What is the proper way to declare a delegate variable?

In MyModel.h, I declared a delegate variable like this:

@property(weak) IBOutlet id <MyProtocol> delegate;

I've also seen a delegate variable declared like this:

@property(weak) IBOutlet NSObject <MyProtocol>* delegate;

I'm wondering which I should use.

Also, Xcode 6.2 indicates I'm doing something wrong because when I connect the delegate outlet in IB, Xcode still shows an empty circle to the left of the declaration instead of a filled in circle. This is what I did:

1) In IB, I dragged on Object out of the Library onto the dock, and I changed its class to: MyModel.

2) In IB, I dragged another Object onto the dock, and I changed its class to: MyController. I declared the MyController class like this:

@interface MyController : NSObject <MyProtocol>

@property(strong) IBOutlet MyModel* model;

@end

3) In IB, I hooked up the delegate outlet for the MyModel Object to the MyController Object.

But in Xcode, it still shows an empty circle to the left of the line:

@property(weak) IBOutlet id <MyProtocol> delegate;

In other words, Xcode is saying the outlet is not connected to anything--yet my app is able to communicate with the controller using the delegate property.

If I delete <MyProtocol> from that line, the circle to the left of the line fills in, i.e. Xcode is saying the outlet is now connected to something. Is that an Xcode bug?

Here are the files for my HelloDelegate app:

MyProtocol.h:

//
//  MyProtocol.h
//  HelloDelegate
//


@class MyModel;  //#import "MyModel.h" doesn't work for some reason

@protocol MyProtocol

-(void)sayHello:(MyModel*)model;

@end

MyModel.h:

//
//  MyModel.h
//  HelloDelegate
//

#import <Foundation/Foundation.h>
#import "MyController.h"

@interface MyModel : NSObject

@property NSString* name;

-(id)initWithName:(NSString*)name;
-(void)doStuff;

@end

MyModel.m:

//
//  MyModel.m
//  HelloDelegate
//

#import "MyModel.h"

@interface MyModel()

@property(weak) IBOutlet id <MyProtocol> delegate;


@end


@implementation MyModel

-(void)doStuff {
    [[self delegate] sayHello:self];
}

-(id) init {
    return [self initWithName:@"world"];
}

//Designated initializer:
-(id) initWithName:(NSString *)name {

    if (self = [super init]) {
        [self setName:name];
    }

    return self;
}


@end

MyController.h:

//
//  MyController.h
//  HelloDelegate
//


#import <Foundation/Foundation.h>
#import "MyProtocol.h"

@interface MyController : NSObject <MyProtocol>

@property(strong) IBOutlet MyModel* model;

@end

MyController.m:

//
//  MyController.m
//  HelloDelegate
//


#import "MyController.h"
#import "MyModel.h"
#import <Cocoa/Cocoa.h>

@interface MyController()

@property(weak) IBOutlet NSTextField* label;

@end

@implementation MyController

-(void)sayHello:(MyModel*)model {

    NSString* labelText = [NSString stringWithFormat:@"Hello, %@!", [model name]];
    [[self label] setStringValue:labelText];
}


@end

AppDelegate.m:

//
//  AppDelegate.m
//  HelloDelegate
//

#import "AppDelegate.h"
#import "MyController.h"
#import "MyModel.h"

@interface AppDelegate ()

@property (weak) IBOutlet NSWindow *window;
@property (strong) IBOutlet MyController* controller;

@end


@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application

    [[[self controller] model] doStuff];

}

- (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
}

@end

Upvotes: 0

Views: 127

Answers (1)

matt
matt

Reputation: 534950

The main difference comes along when you type something as id <SomeProtocol> and then try to send it a message such as respondsToSelector: and the compiler won't let you. It comes as a surprise - or at least it sure came as a surprise to me - that id <SomeProtocol> is not a form of id. The only messages you can send to such a beast without casting are those defined in the protocol. That's in stark contrast to id plain and simple, which can be sent any known message.

Thus, in my view, as in that of those who know better than I, NSObject <SomeProtocol>* is better, because now this thing is seen by the compiler as an NSObject, and can be sent all the messages declared for NSObject.

Upvotes: 1

Related Questions