2009-12-13 3 views
0

저는 Photo 애플 리케이션과 비슷한 방식으로 UIScroller에서 여러 UIImageViews를 표시하기위한 작은 응용 프로그램을 보유하고 있습니다. 나는 항목을 선택할 때, (배열에 추가 된) 사진의 XML 문서를 파싱하고 이미지를 표시하는 UIViewController를 추가하는 TableView를 가지고 있습니다.여러 개의 UIView, dealloc 및 보유

문제는 탭 막대 항목을 클릭하면 이미지를 표시하고 사용 된 모든 메모리를 해제하는보기를 제거한 후에 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에 있습니다. 그것은 여러 ImageViewController를 추가합니다.

- (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를 제거하고 사용되는 메모리를 확보 ALL 아이의 파단에 delloc를 호출 할 예정이다.

어디가 잘못 되었나요? 어떤 도움을 주시면 감사하겠습니다.

감사합니다.

답변

0

내 고객을 설득 한 후 나는이 문제를 해결하기 위해 three20 프레임 워크를 사용했습니다.

2

귀하의 AlbumViewController는 여전히 뷰에 대한 참조를 보유하고 있으므로 해당 참조를 릴리스 할 때까지 뷰가 해제되지 않습니다. 그러나 이것은 좋은 일입니다.

사용자가 화면을 변경할 때마다 메모리를 확보 할 염려는 없습니다. 서로 다른 시각에서 앞뒤로 움직일 때 느려질 것입니다. 시스템 메모리가 부족하면 모든보기 컨트롤러에서 didReceiveMemoryWarning이 호출되어 표시되지 않는 경우보기를 해제합니다.

당신은 좀 더 똑똑한 당신이 할당/대신 AlbumsViewController에서 populateScrollers를 호출, 또한 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]; 
} 

을 해제 AlbumViewController의 setArrPhotos 방법에 부르지 만, 방법에 대한되고 싶은 경우에만 arrPhotos 변경되었습니다. 예를 들어 사용자가 계속해서 또 다시 같은 앨범을 볼가는 경우

- (void)setArrPhotos:(NSArray *)newArrPhotos { 
    if(newArrPhotos != arrPhotos) 
    { 
     [arrPhotos release]; 
     arrPhotos = [newArrPhotos retain]; 
     [self populateScrollers]; 
    } 
} 

이 방법은, 당신은 동일한 뷰 계층을 다시하지 않을 것이다.

+0

환호성. 귀하의 변경 사항을 구현했지만 이해가되지만 여전히 didReceiveMemoryWarning에 문제가있는 것으로 보입니다. NSLog (@ "여기")를 추가했습니다. 언제 타격하는지 확인합니다. 문제는 앱 충돌과 동시에 발생합니다. albumViewController와 자식 뷰를 dealloc한다고 생각하는 것이 맞습니까? –

+0

코드에서 dealloc을 호출하고 싶지는 않습니다. 객체의 보유 개수가 0에 도달하면 자동으로 호출됩니다. albumViewController를 해제하고 싶지만 뷰가 현재 표시되지 않는 경우에만 (따라서 위 코드에서 수퍼 뷰 확인). 또한 자식 뷰를 dealloc 할 필요도 없습니다. albumViewController의 보유 개수가 0에 도달하면 자동으로 뷰가 릴리즈되고 뷰의 자식 뷰가 릴리스됩니다. 문제가 계속되면 언제든지 새 코드를 게시하십시오. – Jacques

+0

나는 실제로 dealloc을 직접 호출하지 않고, 해제하고 유지 된 포인터를 nil로 설정한다. 또한 약간의 리팩터링을 수행했지만 아직 이미지가 많이 표시되는 앨범에 앨범을 표시하는 데 문제가 있습니다. 두 앨범에서 didReceiveMemoryWarning을 호출했지만 다음 이미지를 표시 할 때 여전히 충돌합니다. 프로젝트를 살펴보고 내가 실패한 곳을 볼 수 있는지 알아볼 수 있습니까? 여기에 사본이 있습니다 http://www.gretanova.com/misc/Rock_Photography_v2.zip. 도와 줘서 고마워. –