多个UIViews,dealloc和retain

时间:2009-12-13 18:11:00

标签: iphone memory uiviewcontroller dealloc

我有一个小应用程序,用于以与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释放已用内存。

哪里出错了?任何帮助将不胜感激。

感谢。

2 个答案:

答案 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框架来解决这个问题。