0

誰かがこれで私を助けてくれることを願っています。簡単な質問であるべきことに対する答えを見つけるのに苦労しています。ところで、これは何年にもわたって c と c# を使用してきた私の最初の主要な obj-c プロジェクトなので、私が失敗していることを遠慮なく指摘してください。

写真のアルバムを UIScrollView にロードするように設計された iPhone アプリがあります。また、同じプロセスを使用しますが、単一の画像のみを表示するランダム画像機能もあります。次のように機能します。

  1. 解析された写真のランダム URL へのパスを含む外部 XML フィード (ruby-on-rails Web サイトに保存されている) を読み取ります。
  2. URL のコンテンツは、NSURLConnection を使用して NSData にダウンロードされます。
  3. ScrollView が作成され、プッシュされます
  4. サブクラス化された UIView は UIImageView を割り当て、NSData を使用して UIImage を割り当て、UIimage で UIImageView を初期化し、最後に imageview を UIView に追加します。
  5. 次に、親ビューは UIView を UIScrollView に追加し、これが前面にプッシュされます。

このプロセスは、次のランダム イメージが必要になったときに再び発生します。いくつかの UIView が UIScrollView に追加されることを除いて、画像のアルバム全体を表示するときにも同じプロセスを使用します。

問題は、必要に応じて release と delloc を使用しているにもかかわらず、次の画像が要求されたときに NSURLConnection と UIImage で使用されているメモリがメモリから解放されていないことをアクティビティ ツールが示していることです。これは、アプリを iPhone にビルドすることでさらに証明されます。複数の画像を連続してリクエストすると、おそらくメモリ消費が原因でアプリがクラッシュします。

以下は、契約上の合意によりプロジェクト全体を投稿できないため、コードの一部です。

URLDownload クラス (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 クラス

@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 サブクラス

@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];
}

画像がどのように表示されているかのサンプルコード

- (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];

}

次の画像は、何が起こっているかを説明するためにすべての割り当てを示しています。1 は起動時の割り当てを示し、2 は最初のイメージがロードされた後を示し、3 は 2 番目のイメージがロードされた後を示します。

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

みんなありがとう、リー

4

1 に答える 1

1

いくつかのことが突き出ています。たとえば、URLDownload クラス内では、return ステートメントの後に配置されているため、[request release] への呼び出しに到達することはありません。

return [request urlData];
[request release];
于 2009-10-30T03:17:49.997 に答える