2009-10-28 21 views
0

J'espère que quelqu'un pourra m'aider avec ça. J'ai du mal à trouver une réponse à ce qui devrait être une question facile. En passant, c'est mon premier projet majeur d'obj-c après des années d'utilisation de c et C#, alors n'hésitez pas à signaler les choses sur lesquelles j'échoue.Allocation mémoire, version et NSURLConnection dans l'application iPhone

J'ai une application iPhone conçue pour charger un album de photos dans un UIScrollView. Il a également une fonction d'image aléatoire qui utilise le même processus mais n'affiche qu'une seule image. Cela fonctionne comme suit:

  1. Lire un flux XML externe (stocké sur le site Web ruby-on-rails) qui contient un chemin vers une URL aléatoire de photo une fois analysée.
  2. Le contenu de l'URL est téléchargé à l'aide de NSURLConnection to NSData.
  3. ScrollView est créé et poussé
  4. UIView allocs un sous-classé UIImageView, allocs un UIImage avec le NSData qui, INIT le UIImageView avec le UIImage et ajoute enfin le imageview au UIView.
  5. La vue parent ajoute ensuite UIView à UIScrollView qui est ensuite déplacé vers l'avant.

Ce processus se produit à nouveau lorsque l'image aléatoire suivante est requise. Il utilise également le même processus lors de l'affichage d'un album entier d'images, sauf que plusieurs UIViews sont ajoutés à UIScrollView. Le problème est, malgré l'utilisation de release et de delloc, le cas échéant, l'outil d'activité indique que la mémoire utilisée par NSURLConnection et UIImage n'est pas libérée de la mémoire lorsque l'image suivante est demandée. Ceci est encore prouvé en construisant l'application à l'iPhone. Demander plusieurs images dans une rangée provoque l'accident de l'application vraisemblablement de la consommation de mémoire. Ci-dessous une partie du code car je suis incapable de poster l'ensemble du projet en raison d'accords contractuels.

classe URLDownload (utilise DataDownload)

@implementation URLDownload 
    -(NSData *)GetURL:(NSURL *)strURL 
{ 

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

    DataDownload *request = [DataDownload alloc]; 
request.strURL = strURL; 
[request init]; 

NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 
while (request.isLoading && [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); 

[pool release]; 

return [request urlData]; 
[request release]; 

} 

DataDownload classe

@implementation DataDownload 
@synthesize urlData, connection, strURL, isLoading; 

- (id)init 
{ 
if(self = [super init]) 
{ 

    self.isLoading = YES; 

    NSURLRequest *dataRequest = [NSURLRequest requestWithURL:self.strURL 
              cachePolicy:NSURLRequestReloadIgnoringCacheData 
             timeoutInterval:60]; 

    /* establish the connection */ 
    self.connection = [[NSURLConnection alloc] 
       initWithRequest:dataRequest 
       delegate:self 
    ]; 

    if (connection == nil) { 
     self.urlData = nil; 
    } else { 
     self.urlData = [NSMutableData data]; 
    } 

} 

return self; 

} 

- (void)dealloc { 
[connection cancel]; 
[connection release]; 
[urlData release]; 
[strURL release]; 
[super dealloc]; 
} 

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { 
return nil; 
} 

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response 
{ 
[urlData setLength:0]; 
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 
} 

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)incrementalData 
{ 
[self.urlData appendData:incrementalData]; 
} 

-(void)connectionDidFinishLoading:(NSURLConnection*)connection 
{ 
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 
self.isLoading = NO; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    self.isLoading = NO; 
} 

@end 

ImageView sous-classe

@implementation ImageView 

@synthesize strURL, imvImageView, image, currentlyRotated, imgOptionsView, startDate; 

- (id)initWithFrame:(CGRect)frame { 
if (self = [super initWithFrame:frame]) {  

    self.imvImageView = [UIImageView alloc];  

    if (self.strURL != nil){ 
     [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 
     NSData *datImageData = [NSData dataWithContentsOfURL: [NSURL URLWithString:self.strURL]]; 
     [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 

     self.image = [UIImage imageWithData: datImageData]; 


     CGSize imgSize = image.size; 
     CGFloat fltWidth = imgSize.width; 
     CGFloat fltHeight = imgSize.height; 

     [imvImageView initWithImage:image]; 

     // If landscape rotate image 
     if (fltWidth > fltHeight){ 
      imvImageView.frame = CGRectMake(-80.0, 80.0, 480.0, 320.0); 

      CGAffineTransform rotate = CGAffineTransformMakeRotation(-1.57079633); 
      [imvImageView setTransform:rotate]; 

      self.currentlyRotated = YES; 
     }else{ 
      imvImageView.frame = CGRectMake(0.0, 0.0, 320.0, 480.0); 

      self.currentlyRotated = NO; 
     } 

     [image release]; 
    }else{ 
     self.image = [UIImage alloc]; 
     [imvImageView initWithImage:image]; 
     [image release]; 
    } 

    [self addSubview:imvImageView]; 

} 

[imvImageView release]; 

return self; 
} 

- (void)drawRect:(CGRect)rect { 
// Drawing code 
} 


- (void)dealloc { 
[strURL release]; 
[imvImageView release]; 
[image release]; 
[imgOptionsView release]; 
[startDate release]; 
[super dealloc]; 
} 

Exemple de code de la façon dont les images sont affichées

- (void)displayImage:(NSString *)strURL { 
NSString *strFullURL = @"http://www.marklatham.co.uk"; 
strFullURL = [strFullURL stringByAppendingString:strURL]; 

self.scroller = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0)]; 
[scroller setContentSize:CGSizeMake(320.0, 540.0)]; 
[self.view addSubview:scroller]; 

CGRect rect = CGRectMake(0.0, 0.0, 320.0, 480.0); 
self.imageView = [ImageView alloc]; 
imageView.strURL = strFullURL; 
[imageView initWithFrame:rect]; 
[scroller addSubview:imageView]; 

[scroller release]; 
[imageView release]; 

} 

Les images suivantes montrent toutes les allocations pour illustrer ce qui se passe. 1 montre alloc au démarrage, 2 spectacles après le chargement de la première image et 3 après après la deuxième image.

http://www.gretanova.com/misc/iphone/1.png & 2.png 3.png &

Merci à tous, Lee

+0

Vérifiez cette question similaire: http://stackoverflow.com/questions/1632168/ quand-appeler-libérer-sur-nsurlconnection-delegate –

Répondre

1

Un couple de choses à coller.Par exemple dans la classe URLDownload l'appel à [demande la libération] ne sera jamais atteint comme placé après la déclaration de retour

return [request urlData]; 
[request release];