2009-05-21 14 views
2

Ich arbeite gerade an einem iPhone-Spiel und muss einige Animationen im laufenden Betrieb erstellen. Die Animation basiert auf mehreren Bildern, und da der Bereich der Bildkombinationen zu groß ist und es unmöglich ist, alle Sequenzen vorab zu erstellen, würde ich gerne jedes Mal, wenn sich die Situation ändert, eine Reihe von Bildern neu berechnen können.Speicherlecks in der Bild-Erstellungsfunktion

Die Funktion erstellt eine Reihe von Bildern, die als Animationssequenz verwendet werden. Ich muss mit zwei Dinge helfen:

  1. Es gibt mehrere große Speicherlecks sind, dass ich Schwierigkeiten habe zu finden - ich brauche Hilfe sie
  2. Ortung Da ich auf das iPhone neu bin, was ich wissen will, ob es ist ein besserer Weg, es zu tun, wenn Sie einen besseren Vorschlag haben, wie es zu schreiben, bitte teilen ...

Code:

(void) updateImages:(int) smallPicID 
{ 
    CGRect smallPicRect; 
    smallPicRect.size = CGSizeMake(25.0f, 25.0f); 

    //TODO: add smallPic location for every image. Currently the values only match the first image... 
    static const CGPoint smallPicLocation[11][SMALLPIC_LOCATION_COUNT] = 
    { 
     { {126.0f, 153.0f},{105.0f, 176.0f}, {115.0f, 205.0f}, {145.0f, 211.0f}, {166.0f, 188.0f}, {156.0f, 159.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} } 
    }; 

    for(int i = 0; i < self.m_finalImages.count; ++i) 
    { 
     // start with base image 
     UIImage * baseImg = [self.m_finalImagesEmpty objectAtIndex:i]; 
     CGImageRef baseImgCtx = baseImg.CGImage; 

     // Create the bitmap context that matches the baseImg parameters 
     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
     CGContextRef newImgCtx = CGBitmapContextCreate(NULL, 
                 CGImageGetWidth(baseImgCtx), 
                 CGImageGetHeight(baseImgCtx), 
                 8, 0, colorSpace, 
                 (kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst)); 
     CGColorSpaceRelease(colorSpace); 

     if (newImgCtx == NULL) 
     { 
      // error creating context 
      assert(0); 
      return; 
     } 

     // Get empty drum image width, height. 
     size_t w = CGImageGetWidth(baseImgCtx); 
     size_t h = CGImageGetHeight(baseImgCtx); 
     CGRect rect = {{0,0},{w,h}}; 

     // Draw the image to the bitmap context. 
     // newImgCtx now contains the full empty drum image. 
     CGContextDrawImage(newImgCtx, rect, baseImgCtx); 

     CGContextSaveGState(newImgCtx); 
     // translate & scale because of origin difference between UIKit and CG 
     CGContextTranslateCTM(newImgCtx, 0, h); 
     CGContextScaleCTM(newImgCtx, 1, -1); 

     int startLocation = 0; 
     int endLocation = SMALLPIC_LOCATION_COUNT; 

     // for each location 
     for(int j = startLocation; j < endLocation; j++) 
     { 
      // if its empty, nothing to do, move to next bullet 
      if (m_locationStatus[j] == CY_EMPTY) 
       continue; 

      UIImage * srcImg; 
      switch (m_locationStatus[j]) 
      { 
       case CY_FULL: srcImg = [self.m_finalImagesLoaded objectAtIndex:i]; break; 
       case CY_USED: srcImg = [self.m_finalImagesSpent objectAtIndex:i]; break; 
      } 

      // create small image containing only the smallpic from the src img 
      smallPicRect.origin = smallPicLocation[i][j]; 
      CGImageRef smallpicCGImg = CGImageCreateWithImageInRect(srcImg.CGImage, smallPicRect); 

      // draw the smallpic into the new context 
      CGContextDrawImage(newImgCtx, smallPicRect, smallpicCGImg);   

      CGImageRelease(smallpicCGImg); 
     } 

     CGContextRestoreGState(newImgCtx); 

     // update the image from the context 
     UIImage *baseImg = [self.m_finalImages objectAtIndex:i]; 
     CGImageRef imgref = CGBitmapContextCreateImage(newImgCtx); 
     //[baseImg release]; 
     [baseImg initWithCGImage:imgref]; 

     CGContextRelease(newImgCtx); 
    } 
} 
+0

Hier ist ein verwandter Thread auf Apples Website: http://discussions.apple.com/thread.jspa?threadID=1664673 – Demi

Antwort

2

die ersten Dinge, die mich herausspringen sind die Erstellung von imgref near Das Ende mit einer CGBitmapContextCreateImage(), aber keine übereinstimmende CGImageRelease(), und die BaseImg InitWithCGImage: Nachricht, die nur Speicher kaut. Ich glaube, Sie wollen den Abschnitt ersetzen, die mit „aktualisiert das Bild aus dem Kontext“ mit so etwas wie:

CGImageRef imgref = CGBitmapContextCreateImage(newImgCtx); 
UIImage *replacmentBaseImg = [[UIImage alloc] initWithCGImage:imgref]; 
CGImageRelease(imgref); 

[self.m_finalImages replaceObjectAtIndex:i withObject:replacementBaseImg]; 
[replacementBaseImg release]; 

CGContextRelease(newImgCtx); 

Dies setzt voraus, dass m_finalImages ein NSMutableArray ist und dass Sie haben Ihre anderen Bilder korrekt freigegeben, die eingefügt wurden in diesem Array, so dass, wenn Sie sie ersetzen, sie freigegeben werden.

Bei einer größeren strukturellen Notiz möchten Sie vielleicht sehen, wie Sie kleinere Unterbilder in einzelne CALayers zeichnen und dann diese Ebenen an den verschiedenen Stellen in den Bildschirm und aus dem Bildschirm wechseln, um Ihre Animation auszuführen. Quartz-Zeichnen ist teuer, und CALayers sind zwischengespeicherte Bilder, die als Texturen auf der GPU gespeichert werden. Andere Leute haben diese Sprite-basierten Animationen mit CALayers durchgeführt und beeindruckende Leistung erzielt.