我有一个小应用程序,用于以与Photo应用程序类似的方式在UIScroller中显示多个UIImageViews。我有一个TableView,当我选择一个项目时,解析照片的XML文档(添加到数组中)并添加一个显示图像的UIViewController。
问题是我有一个标签栏控制器,在单击标签栏项后,应该在删除显示图像的视图并释放所有已用内存后返回到TableView。问题是我无法弄清楚如何实现这一目标。是否缺乏对我不了解的记忆规则的理解。
这是我遇到问题的过程。
表视图控制器
这是在parserDidEndDocument之后调用的:从标签栏项目调用backToMenu。
@interface AlbumsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
AlbumViewController *albumViewController;
}
@property (nonatomic, retain) AlbumViewController *albumViewController;
- (void)displayPhotos {
albumViewController = [[AlbumViewController alloc] initWithNibName:@"AlbumView" bundle:nil];
albumViewController.parentView = self;
albumViewController.arrPhotos = self.arrCurrentSetOfPhotos;
[self.view addSubview:albumViewController.view];
[albumViewController populateScroller];
}
- (void)backToMenu {
[albumViewController.view removeFromSuperview];
}
相册视图控制器
这是一个包含UIScroller和UIPageControl的UIViewController。它添加了几个ImageViewControllers。
- (void)populateScroller {
imagesScroller.pagingEnabled = YES;
imagesScroller.contentSize = CGSizeMake(imagesScroller.frame.size.width * [self.arrPhotos count], 380);
imagesScroller.showsHorizontalScrollIndicator = NO;
imagesScroller.showsVerticalScrollIndicator = NO;
imagesScroller.scrollsToTop = NO;
imagesScroller.delegate = self;
imagesScroller.backgroundColor = [UIColor blackColor];
pageControl.numberOfPages = [self.arrPhotos count];
pageControl.currentPage = 0;
pageControl.backgroundColor = [UIColor blackColor];
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (int i = 0; i < [self.arrPhotos count]; i++) {
CGRect frame = imagesScroller.frame;
frame.origin.x = frame.size.width * i;
frame.origin.y = 0;
NSString *strImagePath = [self.arrPhotos objectAtIndex:i];
ImageViewController *imageViewController = [ImageViewController alloc];
imageViewController.localImage = YES;
[imageViewController initWithPhotoName:strImagePath];
[controllers addObject:imageViewController];
imageViewController.view.frame = frame;
[imagesScroller addSubview:imageViewController.view];
[imageViewController release];
}
self.viewControllers = controllers;
[controllers release];
}
ImageViewController
这有一种方法。它添加了一个名为ImageView的子类UIView,它处理添加UIImageView。
- (void)loadImage {
NSString *strRootURL = @"http://www.marklatham.co.uk";
CGRect rect = CGRectMake(0.0, 0.0, 320.0, 480.0);
ImageView *imageView = [ImageView alloc];
imageView.strURL = [strRootURL stringByAppendingString:self.strThisPhoto];
imageView.strTmpPrefix = (self.localImage) ? @"_tmp_rockphotothumb_" : @"_tmp_rockphotolarge_";
[imageView initWithFrame:rect];
[self.view addSubview:imageView];
[imageView release];
}
backToMenu函数应该删除/取消分配AlbumViewController并在所有子子视图上调用delloc释放已用内存。
哪里出错了?任何帮助将不胜感激。
感谢。
答案 0 :(得分:2)
您的AlbumViewController仍然保留对视图的引用,因此在您释放该引用之前它不会被释放。但是,这是一件好事。
每次用户更改屏幕时都不要担心释放内存。当它们在不同视图之间来回切换时,它会减慢速度。如果系统内存不足,它将在所有视图控制器上调用didReceiveMemoryWarning,如果它们没有显示,将导致它们释放视图。
您只想更加巧妙地分配/发布albumViewController
- (void)displayPhotos {
////// Only create this view controller if it doesn't exist yet
if(albumViewController == nil) {
albumViewController = [[AlbumViewController alloc] initWithNibName:@"AlbumView" bundle:nil];
}
albumViewController.parentView = self;
albumViewController.arrPhotos = self.arrCurrentSetOfPhotos;
[self.view addSubview:albumViewController.view];
[albumViewController populateScroller];
}
- (void)backToMenu {
[albumViewController.view removeFromSuperview];
//// if you don't do this, you'll have a retain cycle between the two
//// view controllers and neither will ever get released
albumViewController.parentView = nil;
}
- (void)didReceiveMemoryWarning {
///// if the albunViewController isn't in use, go ahead and free its memory
if([self.albumViewController isViewLoaded] && self.albumViewController.view.superview == nil) {
self.albumViewController = nil;
}
[super didReceiveMemoryWarning];
}
此外,不是从AlbumsViewController调用populateScrollers,而是在AlbumViewController的setArrPhotos方法中调用它,但仅限于arrPhotos已更改。例如:
- (void)setArrPhotos:(NSArray *)newArrPhotos {
if(newArrPhotos != arrPhotos)
{
[arrPhotos release];
arrPhotos = [newArrPhotos retain];
[self populateScrollers];
}
}
这样,如果用户一遍又一遍地查看同一个相册,您将不会一遍又一遍地重新创建相同的视图层次结构。
答案 1 :(得分:0)
在说服我的客户之后,我设法通过使用three20框架来解决这个问题。