Ich habe zwei Klassen, die als Delegat einer dritten Klasse fungieren können, und beide implementieren ein formales Protokoll, das ausschließlich aus optionalen Methoden besteht. Eine der Klassen implementiert alles, während eine andere nur einige Methoden implementiert, die mir wichtig sind. Zur Laufzeit, wenn ich die zweite Klasse als Delegat für die dritte Klasse habe und die dritte Klasse schließlich eine der nicht implementierten optionalen Methoden für diesen Delegaten aufruft, erhalte ich einen Laufzeitfehler, der im Wesentlichen lautet: "Ziel reagiert nicht darauf Nachrichtenauswahl. " Ich dachte, dass objective-c diesen Fall richtig behandelt und dass es nichts tun würde, wenn diese Methode nicht wirklich in der Klasse definiert wäre. Könnte es etwas geben, das ich vermisse?Warum verursachen nicht implementierte optionale Protokollmethoden Laufzeitfehler, wenn diese Methode in obj-c aufgerufen wird?
Antwort
Wenn Sie eine optionale Methode Ihrer Delegierten aufrufen, müssen Sie sicherstellen, dass es an den Wähler reagiert es vor dem Aufruf:
if ([delegate respondsToSelector:@selector(optionalMethod)])
[delegate optionalMethod];
Optional Protokoll Methoden einfach bedeuten, das Objekt das Protokoll implementiert haben nicht zu implementieren die betreffende Methode - der Angerufene muss dann unbedingt prüfen, ob das Objekt die Methode vor dem Aufruf implementiert (sonst stürzt man ab, wie Sie bemerkt haben). Diese NSObject HOM Kategorien können hilfreich sein:
@implementation NSObject (Extensions)
- (id)performSelectorIfResponds:(SEL)aSelector
{
if ([self respondsToSelector:aSelector]) {
return [self performSelector:aSelector];
}
return NULL;
}
- (id)performSelectorIfResponds:(SEL)aSelector withObject:(id)anObject
{
if ([self respondsToSelector:aSelector]) {
return [self performSelector:aSelector withObject:anObject];
}
return NULL;
}
@end
Dann können Sie einfach tun:
[delegate performSelectorIfResponds:@selector(optionalMethod)];
nette Vorschläge :) – Kevlar
........ Was ist HOM? – bandejapaisa
HOM = Nachricht höherer Ordnung. –
Blocks könnte eine bessere Lösung. Sie ermöglichen bedingt beliebigen Code auszuführen, basierend auf der Existenz einer Implementierung eines gegebenen Methode:
-(void) performBlock:(void (^)(void))block ifRespondsTo:(SEL) aSelector{
if ([self respondsToSelector:aSelector]) {
block();
}
}
Durch die Nutzung dieser zusätzlich zu NSObject, können Sie bedingt jede @optional Methode ausführen, unabhängig davon, wie viele Parameter könnte es haben .
Siehe How to safely send @optional protocol messages that might not be implemented
Diese Blöcke Lösung funktioniert gut, wenn Sie Ihren Kopf um eingewickelt bekommen, was los ist. Ich habe ein BOOL-Ergebnis hinzugefügt, weil ich in der Lage sein wollte, eine von mehreren optionalen Methoden bedingt auszuführen. Einige Tipps, wenn Sie versuchen, diese Lösung zu implementieren:
Erstens, wenn Sie Erweiterung/Kategorien noch nicht gefunden haben, fügen Sie einfach diese an den Anfang Ihrer Klasse, außerhalb der vorhandenen Klassendefinition. Es wird eine öffentliche oder private Erweiterung sein, je nachdem, wo Sie es hinstellen.
@implementation NSObject (Extensions)
// add block-based execution of optional protocol messages
-(BOOL) performBlock:(void (^)(void))block ifRespondsTo:(SEL) aSelector
{
if ([self respondsToSelector:aSelector]) {
block();
return YES;
}
return NO;
}
@end
Zweitens ist hier, wie Sie es von Ihrem Code aufrufen:
BOOL b = [(NSObject*)self.delegate performBlock:^{
// code to run if the protocol method is implemented
}
ifRespondsTo:@selector(Param1:Param2:ParamN:)];
ersetzen Param1: Param2: ParamN: mit den Namen der einzelnen Parameter für die Protokollverfahren. Jeder sollte mit einem Doppelpunkt enden. Also, wenn Ihr Protokoll Methode wie folgt aussieht:
-(void)dosomething:(id)blah withObj:(id)blah2 andWithObj(id)blah3;
die letzte Zeile würde wie folgt aussehen:
ifRespondsTo:@selector(dosomething:withObj:andWithObj:)];
- 1. Protokolle: Warum wird @ObjC für Konformitätsprüfungen und optionale Anforderungen benötigt?
- 2. Warum wird diese asynchrone C# 4.0-Methode nicht aufgerufen?
- 3. Warum wird diese Methode ausgeführt, ohne dass sie aufgerufen wird?
- 4. Warum diese Funktion nicht aufgerufen wird, wenn jQuery Plugin Aufruf
- 5. wie JavaScript-Methode von MVC4-Link aufgerufen wird (Fehler JavaScript-Laufzeitfehler: Objekt unterstützt diese Aktion nicht)
- 6. Warum wird meine Equals-Methode nicht aufgerufen?
- 7. Warum verursacht diese Ausnahme keinen Laufzeitfehler?
- 8. Warum wird meine paintComponent() -Methode nicht aufgerufen?
- 9. Wie wird diese Java-Methode aufgerufen?
- 10. Warum wird BackgroundWorker.OnDoWork nicht aufgerufen?
- 11. Wenn AppInitialize-Methode in ASP.NET aufgerufen wird?
- 12. Wenn die IEnumerator.Reset() -Methode aufgerufen wird?
- 13. Warum wird onBackPressed() nicht aufgerufen?
- 14. Warum wird PostConstruct nicht aufgerufen?
- 15. Methode onHandleIntent() wird nicht aufgerufen
- 16. Wird diese Schließung ein Speicherleck verursachen?
- 17. UICollectionReusableView-Methode wird nicht aufgerufen
- 18. Warum wird meine KeyPressed-Methode nie aufgerufen?
- 19. Mailer-Methode wird nicht aufgerufen?
- 20. HttpModule Init-Methode wird mehrmals aufgerufen - warum?
- 21. Können statusbehaftete Session-Beans ein Leck verursachen, wenn keine Annotated-Methode @Remove aufgerufen wird?
- 22. setChangeListener Methode wird nicht aufgerufen
- 23. Warum GetVaryByCustomString nicht aufgerufen wird
- 24. Wie wird diese Art von Methode in Java aufgerufen?
- 25. Wie diese Methode in einem Hintergrundarbeiter aufgerufen wird?
- 26. Warum werden nicht verwandte (Autopostback-) Methoden aufgerufen, wenn eine Asp.Net-ListBox-Autopostback-Methode aufgerufen wird?
- 27. Laufzeitfehler ‚438‘: Das Objekt nicht unterstützt diese Eigenschaft oder Methode
- 28. LibGDX - Methode wird nicht aufgerufen
- 29. Interceptor-Methode nicht aufgerufen wird
- 30. MVC3 - Warum wird die GET-Methode im Controller nicht aufgerufen, wenn partiell gerendert wird?
ich so viel vermutet wird, aber ich hatte gehofft, dass ich nicht hinzufügen müssten Diese If-Checks über den gesamten Code. Danke für den Zeiger. – Kevlar