Frage

Dies scheint die klassische Methode zum Scannen von Bildern aus dem iPhone zu sein. Ich habe einen Thread, der aus dem Hauptfaden entsandt wird und nach Codes scannt. Es schafft im Wesentlichen jedes Mal eine neue Benutzeroberfläche und entfernt sie dann.

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    { 
        while (![thread isCancelled]) {
#ifdef DEBUG
            NSLog(@"Decoding Loop");
#endif
        //  [self performSelectorOnMainThread:@selector(updateImageBuffer) withObject:nil waitUntilDone:YES];           
            CGImageRef cgScreen = UIGetScreenImage();
            UIImage *uiimage = [UIImage imageWithCGImage:cgScreen];

            if (uiimage){
                CGSize size = [uiimage size];
                CGRect cropRect = CGRectMake(0.0, 80.0, size.width, 360); // Crop to centre of the screen - makes it more robust
#ifdef DEBUG
                NSLog(@"picked image size = (%f, %f)", size.width, size.height);
#endif
                [decoder decodeImage:uiimage cropRect:cropRect];
            }
            [uiimage release];
            CGImageRelease(cgScreen);
        }
    }
    [pool release];

Das Problem ist, dass die [Pool -Release] einen Fehler_Bad_exc (diesen alten Klassiker) und die Programmbomben verursacht. Mir wurde gesagt, dass es nicht nötig ist, [UIImage -Veröffentlichung] anzurufen, da ich nicht explizit eine UIImage zugeteilt habe, aber dies scheint nicht der Fall zu sein. Wenn ich diese Linie herausnehme, geht das Speicherverbrauch durch das Dach und das Programm beendet den Gebühren für den Mangel an Speicher. Es scheint, dass ich diese Arbeit nicht so haben kann, wie ich es mir möchte.

Gibt es eine Möglichkeit, eine UIimage "an Ort am Platz" zu erstellen? Dh einen Puffer haben, der immer wieder als Benutzeroberfläche geschrieben ist? Ich vermute, das würde funktionieren?

Aktualisieren!

Versuchte, die uikit verwandten Anrufe im Haupt -Thread wie folgt auszuführen:

-(void)performDecode:(id)arg{

    // Perform the decoding in a seperate thread. This should, in theory, bounce back with a 
    // decoded or not decoded message. We can quit at the end of this thread.
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    { 
        while (![thread isCancelled]) {

#ifdef DEBUG
            NSLog(@"Decoding Loop");
#endif
            [self performSelectorOnMainThread:@selector(updateImageBuffer) withObject:nil waitUntilDone:YES];           

            if (uiimage){
                CGSize size = [uiimage size];
                CGRect cropRect = CGRectMake(0.0, 80.0, 320, 360); // Crop to centre of the screen - makes it more robust
#ifdef DEBUG
                NSLog(@"picked image size = (%f, %f)", size.width, size.height);
#endif
                [decoder decodeImage:uiimage cropRect:cropRect];
            }
        }
    }
    [pool drain];


#ifdef DEBUG
    NSLog(@"finished decoding.");
#endif


}

-(void) updateImageBuffer {
    CGImageRef cgScreen = UIGetScreenImage();
    uiimage = [UIImage imageWithCGImage:cgScreen];
    //[uiimage release];
    CGImageRelease(cgScreen);
}

Keine Freude, aber als exc_bad_access seinen hässlichen Kopf aufweckt, wenn man die "Größe" der Benutzeroberfläche greifen möchte

War es hilfreich?

Lösung

Wie von anderen erwähnt, sollten Sie die von Image withcgimage zurückgegebene UIImage nicht freigeben :. Es ist autorelea. Wenn Ihr Pool abfließt, wird versucht, eine Release-Nachricht an Ihre bereits veröffentlichten Bildobjekte zu senden, was zu Ihrem Absturz führt.

Der Grund, warum Ihre Speicherverwendung immer wieder klettert, ist, dass Sie den Autorelease -Pool nur außerhalb der Schleife abtropfen lassen. Ihre autorelequellen Objekte sammeln sich weiter in der Schleife an. (Übrigens müssen Sie Ihren Autorelease -Pool am Ende dieser Methode freigeben, da er derzeit veröffentlicht wird.) Um diese Akkumulation zu verhindern, können Sie den Pool in regelmäßigen Abständen innerhalb der Schleife abtropfen lassen.

Ich würde jedoch vorschlagen, zum Tun zu wechseln [[UIImage alloc] initWithCGImage:cgScreen] und dann das Bild freigeben, wenn er fertig ist. Ich versuche zu vermeiden, dass autorietete Objekte in iPhone -Anwendungen verwendet werden können, um eine engere Kontrolle über die Speicherverwendung und die insgesamt bessere Leistung zu haben.

Andere Tipps

UigetScreenImage () ist privat und undokumentiert, sodass Sie es nicht verwenden können. Wenn Sie nicht sagen, dass nichts darüber darauf hindeutet, dass Sie jetzt cgimageRef cgscreen besitzen, warum veröffentlichen Sie es? Sie haben auch keine Möglichkeit zu wissen, ob es Faden sicher ist und sollte daher davon ausgehen, dass dies nicht der Fall ist. Sie veröffentlichen dann die IIMage *UIImage, die Sie nicht initiert haben, behalten oder kopieren, also besitzen Sie es nicht. Überprüfen Sie die Dokumente.

[uiimage release] ist in diesem Zusammenhang definitiv falsch. Außerdem betont Apple, dass alle UIKIT -Methoden auf dem Hauptfaden ausgeführt werden müssen. Das schließt sich ein UIGetScreenImage() und +[UIImage imageWithCGImage:].

Bearbeiten: Sie erhalten also eine Ausnahme, wenn Sie anrufen -[UIImage size] auf dem falschen Thread. Dies sollte Sie wahrscheinlich nicht überraschen, weil es nicht erlaubt ist.

UIImage *uiimage = [[UIImage alloc] initWithCGImage: cgScreen];

Ausdrücklich feststellte, dass ich am besten weiß, wann das Objekt freigegeben werden soll, schien zu funktionieren. Das virtuelle Gedächtnis nimmt immer noch zu, aber physisch bleibt jetzt konstant. Vielen Dank, dass Sie jedoch auf den Uikit -Thread -Safe -Problem hingewiesen haben. Das ist ein Punkt, den ich verpasst hatte, aber zu diesem Zeitpunkt nicht das Laufen auswirkt.

Außerdem sollte ich darauf hinweisen, dass roter Laser und Quickmark beide diese Methode zum Scannen von Kamerainformationen verwenden;)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top