Mein Programm zeigt eine horizontale Scroll-Oberfläche mit UIImageViews von links nach rechts gefliest. Code wird auf dem UI-Thread ausgeführt, um sicherzustellen, dass den neu sichtbaren UIImageViews ein frisch geladener UIImage zugewiesen ist. Das Laden geschieht auf einem Hintergrundthread.CGImage/UIImage Lazy Laden auf UI-Thread verursacht Stottern
Alles funktioniert fast gut, außer es gibt ein Stottern, da jedes Bild sichtbar wird. Zuerst dachte ich, mein Hintergrundarbeiter würde etwas im UI-Thread sperren. Ich habe viel Zeit damit verbracht, es zu betrachten, und habe schließlich festgestellt, dass das UIImage beim ersten Öffnen des UI-Threads etwas mehr Lazy verarbeitet. Das verwirrt mich, da mein Worker-Thread expliziten Code zum Dekomprimieren von JPEG-Daten hat.
Wie auch immer, auf eine Ahnung habe ich etwas Code geschrieben, um in einen temporären Grafikkontext auf dem Hintergrund-Thread zu rendern und - sicher genug, das Stottern ging weg. Das UIImage wird jetzt in meinem Worker-Thread vorinstalliert. So weit, ist es gut.
Das Problem ist, dass meine neue "Force Lazy Load Image" -Methode unzuverlässig ist. Es verursacht intermittierende EXC_BAD_ACCESS. Ich habe keine Ahnung, was UIImage hinter den Kulissen tut. Vielleicht dekomprimiert es die JPEG-Daten. Wie dem auch sei, die Methode ist:
+ (void)forceLazyLoadOfImage: (UIImage*)image
{
CGImageRef imgRef = image.CGImage;
CGFloat currentWidth = CGImageGetWidth(imgRef);
CGFloat currentHeight = CGImageGetHeight(imgRef);
CGRect bounds = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
CGAffineTransform transform = CGAffineTransformIdentity;
CGFloat scaleRatioX = bounds.size.width/currentWidth;
CGFloat scaleRatioY = bounds.size.height/currentHeight;
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextScaleCTM(context, scaleRatioX, -scaleRatioY);
CGContextTranslateCTM(context, 0, -currentHeight);
CGContextConcatCTM(context, transform);
CGContextDrawImage(context, CGRectMake(0, 0, currentWidth, currentHeight), imgRef);
UIGraphicsEndImageContext();
}
Und die EXC_BAD_ACCESS geschieht auf der CGContextDrawImage Linie. FRAGE 1: Darf ich das in einem anderen Thread als dem UI-Thread tun? FRAGE 2: Was ist der UIImage eigentlich "pre-loading"? FRAGE 3: Was ist der offizielle Weg, um dieses Problem zu lösen?
Vielen Dank für das Lesen, jeder Rat würde sehr geschätzt werden!
hi, danke, dass du dir die Zeit genommen hast, damit zu helfen. Ich kam schließlich zu dieser Erkenntnis. Ich kann mir nur vorstellen, welche Art von unangenehmem nicht-threadsicherem Caching in diesen UI * -Methoden vor sich geht. Meine Schnittstelle ist jetzt stottern frei ..... – JBx
Ich bin verwirrt ... du sagst imageNamed: verursacht faule Datei IO aber .. das Errichten eines Datengegenstandes nicht? Oder sagen Sie, dass Sie die gepoolten Datenobjekte irgendwo sammeln sollten, um daraus zu ziehen? –
Jasconius: Wenn Sie ein UIImage-Objekt erstellen und ihm den Pfad zu einer Datei zuweisen, lädt es möglicherweise nicht das gesamte Bild in den Speicher, bis Sie es zeichnen. Wenn Sie die Datei mit einem NSData-Objekt in den Arbeitsspeicher laden und dann THAT an UIImage übergeben, hat sie keine andere Wahl, als sie im Arbeitsspeicher zu belassen. Was am besten ist, hängt von der spezifischen Situation ab. – benzado