CALayer didDraw

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • CALayer didDraw

    Hallo den MacOS-Entwicklern!

    Ich benütze einen NSView mit backinglayer um sich ändernde Bilder zu zeichnen. Das geht eigentlich super gut und schnell. Nur fehlt mir der konkrete Zeitpunkt an dem das Zeichnen eines Bildes fertig ist damit ich danach den Inhalt des Bildes sicher bearbeiten kann ohne dass man es gleich sieht. Die Bilder werden von einem anderen Thread bearbeitet, weshalb das Timing unabdingbar ist. Der nächstliegende Zeitpunkt zum draw, den ich abgreifen kann ist das updateLayer. Doch das ist immer noch ein klein wenig VOR dem eigentlichen Zeichenvorgang, sodass ich derzeit ein ein sleep mit ein paar microsecs dazugeben muss damit ich den Inhalt des Bildes ändern kann ohne, dass es sich noch im Zeichenvorgang befindet. Unschöner gehts kaum.

    Ich suche also soetwas ähnliches wie ein didDraw. Alle Versuche mit CALayerDelegate oder Subklassen des Layers haben bislang keinen Erfolg gebracht, weil die entsprechenden Funktionen nicht aufgerufen werden.

    Weiß vielleicht von euch jemand wie man sich in den Zeichenvorgang reinhängt ? Wenn man keinen Layer benützt dann wäre das ein drawRect. Wird beim backinglayer aber nicht aufgerufen. Oder gibts eine andere Funktion von der man weiß, dass sie direkt NACH einem draw des Layers aufgerufen wird ?

    Freue mich über jeden Hinweis.
    Danke und Gruß

    Thomas
  • Wenn du den Content per CAanimation änderst, solltest du mit animationDidStop über die Fertigstellung informiert werden.

    Quellcode

    1. @protocol CAAnimationDelegate <NSObject>
    2. @optional
    3. /* Called when the animation begins its active duration. */
    4. - (void)animationDidStart:(CAAnimation *)anim;
    5. /* Called when the animation either completes its active duration or
    6. * is removed from the object it is attached to (i.e. the layer). 'flag'
    7. * is true if the animation reached the end of its active duration
    8. * without being removed. */
    9. - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
    Alles anzeigen
  • Hej, super. Das ist doch mal ein erfrischend einfacher workaround.
    Klappt super! Danke für den Tip!

    Mit einer Ausnahme: Wenn ich den Mauszeiger nicht bewege geht die Wiederholrate in den Keller. Genau genommen dauert die Animation ohne Mausbewegung (gemessen) gut 3 x so lange. Irgendeine Idee wie man das wegbekommt ?

    Konkret:
    Mit Mausbewegung liegt die Ausführungsdauer der Animation bei 0.007 sec und ohne Mausbewegung bei 0.022 sec.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Thomas ()

  • Schnellschuss-Antwort:

    UserInteractions sind die vom System am höchsten periodisierten Actions überhaupt. Sie laufen immer auf dem DispatchQueue.main, wie alle UI-Actions. Wird die Maus bewegt, wird definitiv UI-Arbeit vollbrachtet. Und dieser System-Job kann eine höhere Priorität haben, denn dein Content-Change.

    PS: Hier lässt sich auch der wesentliche Unterschied zwischen RunLoop.main und DispatchQueue.main sehen, aber das nur nebenbei.

    Quellcode

    1. let backgroundQueue = DispatchQueue.global(qos: .userInitiated) // concurrent
    Sowas hier eventuell?
    Kann allerdings auch sein, dass die User-Eingabe einfach mal alles overruled > weil das macht ja auch Sinn, denn was hat der User davon, mit der App nicht mehr interagieren zu können, wenn diese ein Job erledigt.