2016-08-08 91 views
0

Ich entwickle eine iOS-Anwendung, wo ich einen Bildschirm habe, der einige Filter für eine verwandte Suche anzeigt. Jetzt habe ich alle diese Filter als benutzerdefinierte UIViews gemacht, weil sie alle ziemlich unterschiedliche Benutzeroberfläche haben und sie auf verschiedenen Bildschirmen wiederverwendet werden müssen. Trotz ihrer Unterschiede bieten sie alle eine gemeinsame Schnittstelle zum View-Controller, der sie verwaltet. Der View-Controller kümmert sich also nicht darum, was und wie ein FilterView etwas tut. Es geht nur darum, einige Daten an sie weiterzugeben und ihren Zustand durch eine Eigenschaft zurückzugewinnen, die allen gemeinsam ist. Sie alle haben ihre verschiedenen Klassen, die Unterklassen von FilterView einer Unterklasse von UIView sind. Diese FilterView-Klasse stellt eine Schnittstelle dar, die alle diese Unterklassen übernehmen.Unterklasse oder Protokoll, wie?

Diese Methode funktioniert gut, aber das Problem ist, dass alle Methoden und Eigenschaften, die ein filterView darstellen sollte, in der Basisklasse FilterView deklariert sind und wenn ein bestimmter Filter kein Verhalten implementiert, wird standardmäßig das von ihm bereitgestellte Verhalten verwendet Superklasse FilterView. Ich will das nicht. Ich möchte, dass jede FilterView-Unterklasse benötigt wird, um eine Implementierung in der FilterView-API bereitzustellen oder auf andere Weise ihre eigenen Standardwerte bereitzustellen, nicht die Standardwerte einer Superklasse.

Wenn ich ein Protokoll verwenden, um dieses Verhalten zu implementieren, verliere ich die Fähigkeit für alle diese Klassen obligatorisch UIViews sein, die auch eine Voraussetzung ist.

Können Sie vorschlagen, welches Entwurfsmuster ich verwenden soll, um die verschiedenen FilterView-Unterklassen besser zu verwalten?

+0

http://stackoverflow.com/a/1034464/2518285 - "Wenn die abstrakte Klasse wirklich eine Schnittstelle ist (d. H. hat keine konkreten Methodenimplementierungen), die Verwendung eines Objective-C-Protokolls ist die geeignetere Option. " –

+0

http://StackOverflow.com/a/11145006/2518285 –

Antwort

2

Nun, wenn Sie denken, dass alle Ihre Filterobjekte eine UIView bereitstellen müssen, anstatt explizit eine zu sein, können Sie diese Anforderung zum Protokoll hinzufügen. Zum Beispiel:

@protocol FilterObject 

- (UIView *)viewForFilter; 

@end 

// Swift 
protocol FilterObject { 
    func viewForFilter() -> UIView 
} 

Und dann in Klassen, die tatsächlich sindUIView s implementieren es wie folgt aus:

- (UIView *)viewForFilter { 
    return self; 
} 

// Swift 
func viewForFilter() -> UIView { 
    return self 
} 

Der Vollständigkeit halber können Sie auch Art von "Kraft" die Anforderung, Methoden in Unterklassen zu implementieren, indem eine Ausnahme ausgelöst wird, wenn ihre Basisimplementierung aufgerufen wird:

- (void) methodWithoutBaseImplementation { 
    // this goes in the base class 
    [NSException raise:NSInternalInconsistencyException format:@"This method needs to be implemented by subclasses! - %@", NSStringFromSelector(_cmd)]; 
} 

// Swift 
func methodWithoutBaseImplementation() { 
    NSException.raise(NSInternalInconsistencyException, format:"This method needs to be implemented by subclasses! - \(__FUNCTION__)") 
} 

Dieses Muster, um Objective-C/Swift-Klassen "abstrakt" zu machen, kann in einigen externen Bibliotheken gefunden werden. Beachten Sie, dass dies in Swift schwieriger zu erreichen ist, da kein dynamischer Dispatch vorhanden ist. Wenn Sie also Ihre Unterklasse in die Basisklasse umwandeln und eine Methode aufrufen, wird die Basisimplementierung aufgerufen. Ich würde jedoch davon abraten, da der Protokollansatz sicherer ist, da er keinen Pfad zum Absturz Ihrer App erstellt. Ich habe dieses Beispiel nur hinzugefügt, um die Möglichkeit und Vollständigkeit zu veranschaulichen.

0

Definieren Sie ein Protokoll mit nicht optionalen Methoden - "Standardmäßig sind alle in einem Protokoll deklarierten Methoden erforderliche Methoden. Dies bedeutet, dass jede Klasse, die dem Protokoll entspricht, diese Methoden implementieren muss." Definieren Sie eine Klasse, die deklariert, dass sie das Protokoll implementiert. Nun, wenn eine Unterklasse von Ihren Eltern-Klasse geschrieben wird, wird der Compiler-Flag es als Fehler, wenn die vorgeschriebene Methode (n) nicht

implementiert

und in Superklasse können Sie

//In super class 
- (id)someMethod:(aObject*)param 
{ 
    [self doesNotRecognizeSelector:_cmd]; 
    return nil; 
} 

schreiben Sie Ihre App stürzt ab, wenn Unterklasse diese Methode nicht implementieren und Sie brauchen nicht

[super someMethod: param]; 
+0

Ich kann dies bereits tun, ohne ein Protokoll zu verwenden, Methoden in der Basisklasse können implementiert werden, um fatalError zu generieren.Was ich will, ist ein Typ, der diese allgemeine Schnittstelle zusammen mit einer Garantie darstellen kann, dass all diese auch UIViews sind.In Objc kann dies erreicht werden, indem die Variablen deklariert werden, die diese Ansichten vom Typ aber dies kann nicht in Swift durchgeführt werden. – Pranshu

0

Dies nennen kann in schnellen 4 durch die Definition des gemeinsamen Schnittstelle in einem Protokoll namens Filter und dann definieren Filter jetzt klar ausgedrückt werden Anzeigen als:

typealias FilterView = UIView & Filter