SetNeedsDisplay wird verwendet, um die Ansicht (eine Instanz von UIView oder einer UIView-Unterklasse) neu zu rendern oder neu zu zeichnen. Aus unserer Sicht: Es ruft drawRect auf: aber eigentlich bereitet es vorher den Kontext vor und macht die Ansicht bereit, neu gezeichnet zu werden. (Deshalb sollten Sie drawRect: nicht direkt aufrufen)
Ein üblicher Fall ist, wenn Sie die Methode drawRect: implementiert haben (einige Beispiele: Zeichnen von Inhalten mit OpenGL in einer Ansicht oder Zeichnen von Text mit CoreText oder Zeichnen von Grafiken mit CoreGraphics, usw.) Wenn Sie die Zeichnung zu einem bestimmten Zeitpunkt explizit aktualisieren wollen, rufen Sie setNeedsDisplay auf und es wird drawRect: aufgerufen und Ihre Ansicht wird sofort neu gezeichnet. Wenn nicht, wird die drawRect: Methode aufgerufen, wenn sich die Grenzen der Ansicht geändert haben und in einigen anderen Situationen, wenn das System entscheidet, dass es notwendig ist, die Ansicht neu zu zeichnen.
Im Falle einer Schaltfläche brauchen Sie das nicht zu tun, denn wenn die Schaltfläche gedrückt wird, erfolgt sicherlich ein interner Aufruf von setNeedsDisplay, wodurch die Schaltfläche geändert wird usw. (Wer weiß schon, was im Hintergrund passiert. Die Sache ist die, dass man sich nicht um drawRect: kümmern muss, wenn man UIButtons auf diese Weise verwendet)
Sie können das Erscheinungsbild einer Ansicht auch ändern, indem Sie ihre Unterebenen oder Unteransichten verschieben, was nicht notwendigerweise bedeutet, dass die Ansicht neu gezeichnet werden muss. Dies ist der Fall, wenn sich die Ansicht wie ein Container und nicht wie ein Zeichenobjekt verhält.
Eine gute Regel könnte sein, dass Sie setNeedsDisplay nicht explizit aufrufen müssen, wenn Sie die Methode drawRect: nicht implementiert haben.
http://developer.apple.com/iphone/library/documentation/uikit/reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instm/UIView/drawRect :
Ich hoffe, es hilft.
;)
AKTUALISIERUNG: 2009/09/09
die Art und Weise, wie UIButton drawRect: aufruft, hängt von seiner Implementierung ab, und wir sollen uns nicht darum kümmern (zumindest nicht, wenn wir nicht subclassing sind). Aber wenn Sie es wirklich wissen, können Sie es subclass und überschreiben:
- (void) drawRect:(CGRect)frame{
NSLog(@"%s is being called!!!", _cmd);
[super drawRect:frame];
}
und jetzt von einem anderen Objekt aus versuchen, es zu laden, die Größe zu ändern, es zu verschieben, es zu scrollen (falls verfügbar), es auszublenden und die Debug-Konsole zu sehen (Cmd + Shift + R) Ich würde empfehlen, dies nicht nur für einen UIButton, sondern auch für eine normale UIView zu tun. Das wird sicherlich eine klare Vorstellung geben, wenn drawRect: aufgerufen wird ;) (Auch andere Methoden wie layoutSubviews:, etc)
Der Grund, warum ich gesagt habe, dass wir uns nicht um drawRect: in UIButton kümmern sollen, ist, dass wir es nicht brauchen. Wir stellen ein Bild für einen bestimmten Zustand mit setImage:forState: ein und das ist alles. Wir können dieses Bild jederzeit neu einstellen und der Button wird sein Bild je nach Bedarf ändern und es könnte seine Ansicht neu zeichnen, je nachdem, wie die Apple-Ingenieure es entworfen haben.
Bezüglich Ihrer Frage, ob setNeedsDisplay der von mir angegebenen Regel entspricht. Ich glaube ja. Ich habe einen Haltepunkt am Anfang jeder Methode gesetzt und nichts und überprüft, was passiert, wenn setNeedsDisplay aufgerufen wird. Keine der Methoden von LeverView wurde aufgerufen! Dann habe ich die 3 Aufrufe von setNeedsDisplay kommentiert und die Ergebnisse waren die gleichen (iOS4.1). Daher werden diese drei Codezeilen nicht benötigt ;)
Du musst vorsichtig sein, wenn du setNeedsDisplay aufrufst, denn je nach deiner Implementierung könnte es dein Programm sehr langsam machen, da alles neu gezeichnet wird und das wahrscheinlich nicht nötig ist ;)
Pheeew ... lol. Ziemlich langer Beitrag nur über drawRect:
Prost