声明委托变量的正确方法是什么?

时间:2022-08-24 22:16:59

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

在MyModel.h中,我声明了一个这样的委托变量:

@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:

此外,Xcode 6.2表明我做错了,因为当我连接IB中的委托出口时,Xcode仍然在声明的左边显示一个空圆圈而不是填充圆圈。这就是我做的:

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

1)在IB中,我将Object从Library中拖到Dock上,然后将其类更改为: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:

2)在IB中,我将另一个Object拖到了Dock上,我把它的类更改为:MyController。我像这样声明了MyController类:

@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.

3)在IB中,我将MyModel对象的委托出口连接到MyController对象。

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

但是在Xcode中,它仍然在该行的左侧显示一个空白圆圈:

@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.

换句话说,Xcode表示插座没有连接任何东西 - 但我的应用程序能够使用delegate属性与控制器通信。

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?

如果我从该行删除 ,则该行左侧的圆圈将填充,即Xcode表示该插座现已连接到某物。这是一个Xcode错误吗?

Here are the files for my HelloDelegate app:

以下是我的HelloDelegate应用程序的文件:

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

1 个解决方案

#1


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.

当您输入id 的内容然后尝试向它发送一条消息(例如respondsToSelector)时,主要区别在于,并且编译器不会让您。令人惊讶的是 - 或者至少它确实让我感到意外 - id 不是id的形式。您可以发送给没有强制转换的野兽的唯一消息是协议中定义的消息。这与id简单明了形成鲜明对比,可以发送任何已知消息。

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.

因此,在我看来,就像那些比我更了解的人,NSObject *更好,因为现在这个东西被编译器视为NSObject,并且可以发送为NSObject声明的所有消息。

#1


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.

当您输入id 的内容然后尝试向它发送一条消息(例如respondsToSelector)时,主要区别在于,并且编译器不会让您。令人惊讶的是 - 或者至少它确实让我感到意外 - id 不是id的形式。您可以发送给没有强制转换的野兽的唯一消息是协议中定义的消息。这与id简单明了形成鲜明对比,可以发送任何已知消息。

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.

因此,在我看来,就像那些比我更了解的人,NSObject *更好,因为现在这个东西被编译器视为NSObject,并且可以发送为NSObject声明的所有消息。