2015-05-04 5 views
0

В MyModel.h, я объявил переменную делегату, как это:Каков правильный способ объявления переменной-делегата?

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

Я также видел переменный делегат объявленный как это:

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

Я задаюсь вопросом, который следует использовать.

Также Xcode 6.2 указывает, что я делаю что-то неправильно, потому что, когда я соединяю выход делегата в IB, Xcode по-прежнему показывает пустой круг слева от объявления вместо заполненного круга. Это то, что я сделал:

1) В IB я перетащил объект из библиотеки на док-станцию, и я сменил его класс на MyModel.

2) В IB я перетащил еще один объект на док-станцию, и я сменил его класс на MyController. Я объявил MyController класс вроде этого:

@interface MyController : NSObject <MyProtocol> 

@property(strong) IBOutlet MyModel* model; 

@end 

3) В IB, я подключил выход делегата для MyModel объекта к MyController объекта.

Но в Xcode, он по-прежнему показывает пустой кружок слева от линии:

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

Другими словами, Xcode говорит выход не подключен ни к чему - пока мое приложение может связь с контроллером с использованием свойства делегирования.

Если я удалю <MyProtocol> с этой линии, круг слева от линии заполняется, то есть Xcode говорит, что розетка теперь подключена к чему-то. Это ошибка Xcode?

Вот файлы для моего приложения 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 
+0

«Мне интересно, что я должен использовать» Ну, «должно» - это субъективно. Лучше спросить, в чем разница; есть некоторые важные отличия в отношении компилятора. – matt

+0

@matt, Спасибо за ответ. У меня было такое подозрение. Является ли объявление id копией объекта в переменную, тогда как объявление указателя создает (слабую) ссылку? Мне также было интересно узнать, что черная цепочка связи рядом с объявлением переменной. Почему Xcode не заполняет его после того, как я установил соединение в IB? Я чувствую, что Xcode говорит мне, что объявление ошибочно. – 7stud

+1

Нет, это не имеет никакого отношения к управлению памятью, а кругооборот Xcode - это просто причуда (Interface Builder никогда не очень хорошо разбирался в протоколах). – matt

ответ

1

Основное различие приходит, когда вы печатаете что-то, как id <SomeProtocol>, а затем попробуйте отправить ему сообщение, такое как respondsToSelector: и компилятор не позволит вам. Это сюрприз - или, по крайней мере, он уверен came as a surprise to me - что id <SomeProtocol> is не форма id. Только сообщения, которые вы можете отправить такому зверю без кастинга, - это те, которые определены в протоколе.Это резко контрастирует с id простой и простой, что может быть отправлено any известное сообщение.

Таким образом, на мой взгляд, как и у those who know better than I, NSObject <SomeProtocol>* лучше, потому что теперь эта вещь рассматривается компилятором как NSObject и может быть отправлена ​​все сообщения, объявленные для NSObject.

+1

В качестве альтернативы, 'SomeProtocol' может наследовать от протокола NSObject, как это делает большинство протоколов Apple. – jrturton

+0

Извините, что был покрыт вашей первой ссылкой, но я думаю, что стоит упомянуть об этом здесь. – jrturton

+0

@jrturton Согласен, рад, что вы упомянули это явно. – matt

Смежные вопросы