2013-04-12 12 views
5

Jede View-Klasse verfügt über mehrere Init-Methoden - eine, die bereits in UIView enthalten ist, und dann noch weitere -, und jede von ihnen erstellt die gleichen Elemente auf die gleiche Weise. Ich habe daher in der Regel alle eine [self initialSetup]; Methode, die die Einrichtung all dieser Elemente enthält. Das Problem, das ich festgestellt habe, ist, dass, wenn eine Unterklasse auch eine initialSetup-Methode hat, die superclass initialSetup-Methode überschreiben würde und die Oberklasse daher die Methode öffentlich haben müsste, um noch funktionieren zu können. Dies verursacht Probleme mit der Organisation, da die Methode niemals anders als von init aufgerufen werden sollte, also keinen Grund hat öffentlich zu sein.Die beste Methode, um init zu machen, ohne Code zu wiederholen?

Antwort

2

Sie haben ein Problem gefunden, für das es keine perfekte Lösung gibt. Was Sie idealerweise haben sollten, ist eine Methode, die nicht im normalen Sinne unterklassifiziert werden kann und die nur für Instanzen genau dieser Art von Klasse zugänglich ist.

Wo dies ein Risiko ist, scheint es üblich zu sein, den Klassennamen in die Setup-Methode aufzunehmen. Also anstelle von initialSetup haben Sie etwas wie myViewSubclassInitialSetup.

Sie können auch so etwas wie dies an der Spitze Ihrer Methode hinzu:

NSAssert([self isMemberOfClass:[ThisClass class]], 
      @"IniitalSetup called by sub- or superclass") 

Dann wird Ihr Debug-Builds wird eine Ausnahme ausgelöst, wenn eine Unterklasse oder Super Ihre init-Methode aufrufen endet. Das gibt Ihnen einen Platz für einen Haltepunkt und einen Stacktrace, der es Ihnen ermöglichen sollte, das Problem sehr schnell zu finden.

Es fügt Ihren Release-Builds keinen Code hinzu.

2

Ändern Sie den Namen initialSetup in etwas wie initialSetupClassName - Unterklassen, auch wenn sie versehentlich das gleiche Muster verwendet, würde nicht den gleichen Namen verwenden, da sie einen anderen Klassennamen hatten.

Sie können auch ein Präfix "_" für private Methoden verwenden, die Sie lieber nicht aufrufen würden, aber der Subclasser kann das auch tun.

1

Leider Objective C bietet keine Möglichkeit, das auf eine "saubere" Weise zu erreichen. Die ideale Lösung wäre eine geschützte Methode. Aber das ist nicht möglich in Objective C

Apple hatte dieses Problem, als sie die UIGestureRecognizer erstellen. Es gab einige Methoden, die wirklich nicht von jemandem aufgerufen werden sollten, die aber von Unterklassen überschrieben werden mussten. Die Art und Weise, wie sie sich damit auseinandersetzten, bestand darin, eine separate Headerdatei (UIGestureRecognizerSubclass.h) zu erstellen, die eine Kategorie zu dem ursprünglichen UIGestureRecognizer mit diesen "geschützten" Methoden enthält. Der zusätzliche Header wird nur von Unterklassen importiert (d. H. Für Unterklassenzwecke). Weitere Details finden Sie unter UIGestureRecognizer Class Reference.

Natürlich verhindert das nicht, dass irgendjemand die zusätzliche Header-Datei missbraucht, aber es zeigt zumindest deutlich Ihre Absicht und hält Ihren Code gut strukturiert. Auch Sie werden nicht durch automatische Vervollständigung für die zusätzlichen Methoden "belästigt" werden, wenn Sie nur die Klasse verwenden.

Persönlich verwende ich nur einen zusätzlichen Header, wenn es extrem wichtig ist, dass niemand es direkt anruft. In den meisten Fällen denke ich, dass es in Ordnung ist, öffentliche Methoden zu verwenden und notieren Sie, was es bedeutet. Das iOS Framework hat auch viele dieser Fälle. F. e. viele Methoden von UIViewController 's viewDidLoad usw.

2

Es klingt wie Sie einen designierten Initialisierer vermissen.Bestimmen Sie einen Initialisierer als den offiziellen Initiator, der das Setup tatsächlich ausführt, und lassen Sie alle anderen mit einem gewissen Anpassungsgrad angeben. Gewöhnlich ist der designierte Initialisierer derjenige mit den meisten Details. Wenn Sie beispielsweise init, initWithName:, initWithName:age: und initAsFiveYearOldNamed: haben, wird der Initialisierer initWithName:age: und die anderen Initialisierer würden diese Methode nur mit den entsprechend ausgefüllten Argumenten aufrufen.

Verwandte Themen