2009-08-03 19 views
1

Ich versuche, Delegation für eine Klasse zu implementieren, die es Delegat (falls vorhanden) nennen sollte, wenn spezielle Dinge passieren.Wie kann die Delegierung richtig implementiert werden?

aus Wikipedia habe ich diesen Code Beispiel:

@implementation TCScrollView 
-(void)scrollToPoint:(NSPoint)to; 
{ 
    BOOL shouldScroll = YES; 
    // If we have a delegate, and that delegate indeed does implement our delegate method, 
    if(delegate && [delegate respondsToSelector:@selector(scrollView:shouldScrollToPoint:)]) 
    shouldScroll = [delegate scrollView:self shouldScrollToPoint:to]; // ask it if it's okay to scroll to this point. 

    if(!shouldScroll) return; // If not, ignore the scroll request. 

    /// Scrolling code omitted. 
} 
@end 

Wenn ich versuche die alleine, erhalte ich eine Warnung, dass die Methode, die ich auf den Delegierten nenne wurde nicht gefunden. Natürlich war es nicht, weil der Delegat nur durch ID referenziert wird. Es könnte alles sein. Sicher zur Laufzeit, das wird gut funktionieren, weil ich überprüfe, ob es auf selector reagiert. Aber ich will die Warnung in Xcode nicht. Gibt es bessere Muster?

+0

Sie müssen in objective-c nicht nach nil suchen. Es ist zulässig, eine Nachricht an ein Nullobjekt zu senden. – Lounges

+0

In diesem Fall müssen Sie nicht nach nil suchen, da ein BOOL kleiner als sizeof (void *) ist. Für jeden anderen Rückgabetyp, z. B. eine große Struktur, ist der Rückgabewert jedoch undefiniert, und daher ist die Überprüfung auf Null der einzige Weg, um undefiniertes Verhalten zu verhindern. – bbum

Antwort

7

Sie könnten den Delegaten vom ID-Typ sein, der das SomeClassDelegate-Protokoll implementiert. Dazu können Sie in der Kopfzeile Ihrer Someclass konnte (in Ihrem Fall TCScrollView), tun Sie etwas wie folgt aus:

@protocol TCScrollViewDelegate; // forward declaration of the protocol 

@interface TCScrollView { 
    // ... 
    id <TCScrollViewDelegate> delegate; 
} 
@property (assign) id<TCScrollViewDelegate> delegate; 
@end 

@protocol TCScrollViewDelegate 
- (BOOL) scrollView:(TCScrollView *)tcScrollView shouldScrollToPoint:(CGPoint)to; 
@end 

Dann können Sie von Ihrer Implementierung, rufen Sie einfach die Methode auf dem Delegierten:

@implementation TCScrollView 

-(void)scrollToPoint:(NSPoint)to; 
{ 
    BOOL shouldScroll = YES; 
    shouldScroll = [delegate scrollView:self shouldScrollToPoint:to]; // ask it if it's okay to scroll to this point. 
    if(!shouldScroll) return; // If not, ignore the scroll request. 
    /// Scrolling code omitted. 
} 
@end 
0

Nach dem Beispielcode in drvdijk's answer könnte ein Problem auftreten, wenn die Wahrscheinlichkeit besteht, dass delegatenil sein kann, wenn Sie die Delegate-Methode aufrufen.

Der Rückgabewert einer Nachricht an nil gesendet ist nil (aka 0.0 aka 0 aka NO), also wenn delegatenil ist,

[delegate scrollView:self shouldScrollToPoint:to] 

NO zurückkehren wird, was nicht das gewünschte Verhalten könnte in Ihrem Fall. Es ist besser, zuerst zu überprüfen:

if (delegate != nil) { 
    shouldScroll = [delegate scrollView:self shouldScrollToPoint:to] 
} 

Auch, wenn Sie nicht über eine Compiler-Warnung angezeigt werden sollen, wenn sie von NSObject erklärt Nachrichten an Ihre Stellvertretung (wie respondsToSelector:) senden, schließen das NSObject Protokoll in Ihrem Protokollerklärung:

@protocol TScrollViewDelegate <NSObject> 
- (BOOL) scrollView:(TCScrollView *)tcScrollView shouldScrollToPoint:(CGPoint)to; 
@end 
0

Verwenden [NSObject performSelector:]

[delegate performSelector:@selector(scrollView:shouldScrollToPoint:) withObject:self withObject:to]; 

Die Compilerwarnungen werden nicht mehr angezeigt.

Alternativ erstellen Sie ein Prototcol und deklarieren Sie MyProtocol *delegate in Header-Datei.

Verwandte Themen