2010-11-24 11 views
0

In einer meiner Anwendungen für iPad Ich bin der Aufbau der db remote mit einem JSON-String dann in NSArray konvertiert werden, um in Kerndaten eingefügt werden, und dann donload ich rund 600 MB Bilder auf dem iPad. All dies wird in einem Hintergrund-Thread erstellt, der von Anfang an Speicherprobleme verursacht. Ich bekomme das Problem, nesting 3 verschiedene NSAutoreleasePool in der Operation und Freigabe jeder von ihnen an einem geeigneten Punkt. Ich habe weder einen Fehler, noch ein Leck oder eine Warnung. Ich habe mich nur gefragt, ob das ein guter Weg ist oder ich etwas vermisse.verschachtelte NSAutoreleasePool

Hier ein schematisches Beispiel (der eigentliche Code ist ziemlich lang):

- (void)main{ 
@try { 


    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // first pool 
    [managedOC lock]; 
    NSArray *results = [self loadEntitiesWithGroupName:@"Project" andName:@"projects"]; 
    NSAutoreleasePool *prjPool; // second pool 
    for (NSDictionary *thisResult in results) { 
     prjPool = [[NSAutoreleasePool alloc] init]; 

     Project *prj = [[Project alloc] initWithEntity:[NSEntityDescription entityForName:@"Project" inManagedObjectContext:self.managedOC] insertIntoManagedObjectContext:self.managedOC]; 
     prj.name = [thisResult objectForKey:@"name"]; 
     [prj saveThumbnail:[thisResult objectForKey:@"thumbnail"]]; 

     //Slides. Those are the images that take so mutch space. 
     NSArray *slides = [thisResult objectForKey:@"slides"]; 
     NSAutoreleasePool *slidePool; // third pool 
     if(slides != kCFNull){ 
      slidePool = [[NSAutoreleasePool alloc] init]; 
      for(NSDictionary *slide in slides){ 
       Slide *thisSlide = [[Slide alloc] initWithEntity:[NSEntityDescription entityForName:@"Slide" inManagedObjectContext:self.managedOC] insertIntoManagedObjectContext: self.managedOC]; 
       thisSlide.path = prj.path; 
       [thisSlide saveFile:[slide objectForKey:@"file"]]; 
       [prj addSlidesObject:thisSlide]; 
       [thisSlide release]; 
       [slidePool drain]; 
      } 
     } 

     [prj release]; 
     [result release]; 
     [prjPool drain]; 


    } 

    [self.managedOC unlock]; 
    [totResult release]; 
    [pool drain]; 
} 
@catch (NSException * e) { 

} 
+0

Wo und wie Sie tatsächlich Bilder herunterladen? – Vladimir

+0

ist es getan auf [thisSlide saveFile: [Folie objectForKey: @ "Datei"]], wo ich die UIImage aus der heruntergeladenen Datei erstellen und dann verwende ich NSData und NSFileManager zum Speichern in der Anwendung Dokumente Ordner. – cescofry

Antwort

1

Ich bin überrascht, Ihr Code nicht abstürzt. -drain verhält sich genauso wie -release in der Referenz gezählt Umgebung, so dass die folgenden über Veröffentlichungen auf den Pool

slidePool = [[NSAutoreleasePool alloc] init]; // this is in the wrong place 
for(NSDictionary *slide in slides){ 
    Slide *thisSlide = [[Slide alloc] initWithEntity:[NSEntityDescription entityForName:@"Slide" inManagedObjectContext:self.managedOC] insertIntoManagedObjectContext: self.managedOC]; 
    thisSlide.path = prj.path; 
    [thisSlide saveFile:[slide objectForKey:@"file"]]; 
    [prj addSlidesObject:thisSlide]; 
    [thisSlide release]; 
    [slidePool drain]; 
} 

Solange es nur ein Objekt in der slides Sammlung ist. Sie brauchen dies:

for(NSDictionary *slide in slides){ 

    slidePool = [[NSAutoreleasePool alloc] init]; // this is in the right place 

    Slide *thisSlide = [[Slide alloc] initWithEntity:[NSEntityDescription entityForName:@"Slide" inManagedObjectContext:self.managedOC] insertIntoManagedObjectContext: self.managedOC]; 
    thisSlide.path = prj.path; 
    [thisSlide saveFile:[slide objectForKey:@"file"]]; 
    [prj addSlidesObject:thisSlide]; 
    [thisSlide release]; 
    [slidePool drain]; 
} 

Ansonsten haben Sie die richtige allgemeine Idee.

Sie sollten Ihren äußersten Pool im finally-Block Ihrer Exception-Handler entwässern, so dass es nicht, wenn eine Ausnahme ausgelöst wird übersprungen, das heißt, sollten Sie dies tun:

- (void)main{ 

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // first pool 

    @try { 

     // Do al your stuff 
    } 
    @catch (NSException * e) { 

    } 
    @finally 
    { 
     [pool drain]; 
    } 
} 
+0

Sie haben eigentlich recht, über die Position von slidePool, aber aber der Code ist nie abgestürzt. Danke auch für das @finally Bit. Wie auch immer ist es korrekt die Anwendung von mehreren verschachtelten Autorelease-Pools? – cescofry

+0

@cescofry: Ja, abgesehen von der falschen Stelle der alloc von SlidePool, ist es in Ordnung. – JeremyP

Verwandte Themen