0

我希望有人可以帮助我解决这个问题。我正在努力寻找应该是一个简单问题的答案。顺便说一句,这是我使用 c 和 c# 多年后的第一个主要 obj-c 项目,所以请随时指出我失败的地方。

我有一个 iPhone 应用程序,旨在将相册加载到 UIScrollView 中。它还具有随机图像功能,该功能使用相同的过程,但仅显示单个图像。它是这样工作的:

  1. 读取外部 XML 提要(存储在 ruby​​-on-rails 网站上),其中包含解析后照片的随机 url 的路径。
  2. 使用 NSURLConnection 将 URL 的内容下载到 NSData。
  3. 创建并推送 ScrollView
  4. 子类 UIView 分配一个 UIImageView,分配一个带有 NSData 的 UIImage,用 UIimage 初始化 UIImageView,最后将 imageview 添加到 UIView。
  5. 然后,父视图将 UIView 添加到 UIScrollView,然后将其推到前面。

当需要下一个随机图像时,此过程再次发生。除了向 UIScrollView 添加了几个 UIView 之外,它在显示整个图像专辑时也使用相同的过程。

问题是,尽管在适当的情况下使用了 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];

}

数据下载类

@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 显示第二个图像后。

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

谢谢大家,李

4

1 回答 1

1

有几件事很突出。例如,在 URLDownload 类中,对 [request release] 的调用将永远不会到达,因为它位于 return 语句之后

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