2013-02-04 3 views
0

내 앱의보기 중 하나에 이미지 목록이 표시됩니다. 그 목록을 여러 번 스크롤하면 내 앱이 다운됩니다. 필자는 악기로 그 프로파일을 만들었고 목록의 셀은 목록이 스크롤 될 때 더 많은 메모리를 사용하고있는 것처럼 보입니다.iOS : UITableView를 스크롤 할 때 앱 크래시/메모리가 채워짐

tableView : cellForRowAtIndexPath에서 반환 할 때 사용자 지정 UITableCell이 '자동 게시'되어야합니까? (내가 할 경우 iOS 4.3에서 충돌이 발생합니다.) iOS 5.0 및 6.1에서는 괜찮습니다.

이 맞춤식 UITableCell에는 'contentView'에 그려진 그림이 여러 개 있습니다. 그 그림들은 실제로 배경 이미지를 설정하는 커스텀 UIButton입니다.

이미지는 사용자있는 UIButton에 대한 HJManagedImageV

코드 관리 : 사용자 정의 셀 여기

@implementation ProductGridCellIpad 

@synthesize products, parentController; 

- (void)initializeWithProducts:(NSMutableArray *)productsToShow{ 

    self.products = productsToShow; 

    // clear possible old subviews 
    for (UIView *v in self.contentView.subviews) { 
     [v removeFromSuperview]; 
    } 

    NSInteger width = 240; 
    NSInteger height = 240; 

    Product *product0 = [products objectAtIndex:0]; 

    self.productTile0 = [[[ProductTileButtonIpad alloc] initWithFrame:CGRectMake(12, 12, width, height) andProduct:product0] autorelease]; 

    [self.productTile0 addTarget:self.parentController action:@selector(selectedProduct:) forControlEvents:UIControlEventTouchUpInside]; 

    [self.contentView addSubview:self.productTile0]; 

    [self.productTile0 release]; 

    if ([self.products count] > 1) { 

     Product *product1 = [products objectAtIndex:1]; 

     self.productTile1 = [[[ProductTileButtonIpad alloc] initWithFrame:CGRectMake(12 + width + 12, 12, width, height) andProduct:product1] autorelease]; 

     [self.productTile1 addTarget:self.parentController action:@selector(selectedProduct:) forControlEvents:UIControlEventTouchUpInside]; 

     [self.contentView addSubview:self.productTile1]; 

     [self.productTile1 release]; 
    } 

    if ([self.products count] > 2) { 

     Product *product2 = [products objectAtIndex:2]; 

     self.productTile2 = [[[ProductTileButtonIpad alloc] initWithFrame:CGRectMake(2*(12 + width) + 12, 12, width, height) andProduct:product2] autorelease]; 

     [self.productTile2 addTarget:self.parentController action:@selector(selectedProduct:) forControlEvents:UIControlEventTouchUpInside]; 

     [self.contentView addSubview:self.productTile2]; 

     [self.productTile2 release]; 
    } 
} 

- (void)dealloc { 

    NSLog(@"deallocating ProductGridCellIpad"); 

    if(self.products) 
     [self.products release]; 

    if(self.productTile0) 
     [self.productTile0 release]; 

    if(self.productTile1) 
     [self.productTile1 release]; 

    if(self.productTile2) 
     [self.productTile2 release]; 

    [super dealloc]; 
} 

@end 

및 대한

@implementation ProductTileButtonIpad 

@synthesize product; 

- (id)initWithFrame:(CGRect)frame andProduct:(Product *)aProduct { 

    if (self = [super initWithFrame:frame]) { 

     self.product = aProduct; 

     self.productTileView = [[[HJManagedImageV alloc] initWithFrame:self.frame] autorelease]; 
     self.productTileView.callbackOnSetImage = self; 
     self.productTileView.url = some picture url 

     [[ImageManager instance] manage:self.productTileView]; 
    } 

    return self; 
} 


#pragma mark - 
#pragma mark HJManagedImageV delegate 

-(void) managedImageSet:(HJManagedImageV*)mi { 

    [self setBackgroundImage:mi.image forState:UIControlStateNormal]; 
} 

-(void) managedImageCancelled:(HJManagedImageV*)mi { 
} 


- (void)dealloc { 

    NSLog(@"deallocating ProductTileButtonIpad"); 

    [self.product release]; 
    [self.productTileView release]; 

    [super dealloc]; 
} 

@end 

코드의 셀 생성 코드 :

NSString *productGridCellIpadIdentifier = @"ProductGridCellIpadIdentifier"; 

    ProductGridCellIpad *cell = [tableView dequeueReusableCellWithIdentifier:productGridCellIpadIdentifier]; 

    if(cell == nil) { 

     cell = [[ProductGridCellIpad alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:productGridCellIpadIdentifier]; 

     [cell setFrame:CGRectMake(0, 0, self.view.frame.size.width, 244)]; 
    } 

    [cell setParentController:self]; 
    [cell initializeWithProducts:products]; 

    return cell; 

지금 바로 iOS 4.3에서 코드가 충돌합니다. iOS 5와 6에서 작동하지만 테이블을 사용/스크롤하는 일정 시간이 지난 후에도 앱이 계속 충돌합니다.

저는 ARC를 사용하지 않습니다.

나는 무슨 일이 일어나고 있는지 확인하기 위해 할당 해제의 방법에 일부 NSLog를 추가하고 나는

내 애플 쉽게 400MB의 메모리 사용량에 도달 "ProductGridCellIpad을 할당 해제", "ProductTileButtonIpad을 할당 해제"하지만 난 못 볼을 많이 볼 수 있습니다.

내가 뭘 잘못하고 있니? 여러분 중 몇몇은 어떤 생각이있는 경우

은, 내 이해를 도울 수있는 아이디어는 그것을 많이 주시면 감사하겠습니다 :)

+0

그게 맞는지는 모르지만 ARC를 사용하지 않으면 셀을 자동으로 내 보내야합니다. –

+1

문제는 초기화 할 때마다 초기화해야한다는 것입니다. 초기화는 한 번만해야합니다. tableview를 사용할 때처럼 (cell == nil) {// Do you initialization} // 여기서 값만 업데이트합니다. .. 여기 초기화가 없습니다 .. – iphonic

+0

@iphonic "당신은 매번 초기화 작업을하고 있습니다"라는 말은 무엇을 의미합니까? 내가 셀 재활용을 사용하기 때문에 ... – Alexis

답변

2

세포가 재사용, 당신은 "ProductGridCellIpad 할당 해제"를 참조해서는 안 스크롤 할 때. 대신 재활용이 정말로 작동하는지 확인하거나 새로운 세포에게 모든 시간을 만들고 유지 여부 :

ProductGridCellIpad *cell = [tableView dequeueReusableCellWithIdentifier:productGridCellIpadIdentifier]; 

if(cell == nil) { 
    cell = [[ProductGridCellIpad alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:productGridCellIpadIdentifier]; 
    [cell setFrame:CGRectMake(0, 0, self.view.frame.size.width, 244)]; 
    NSLog("Cell created"); 
} 
else { 
    NSLog("Cell recycled"); 
} 

을 그 괜찮아, 난이 해제 확인 것입니다. 예를 들어 autorelease와 release 모두 ​​"self.productTile2"가 있습니다. 이로 인해 메모리 관리가 혼동 될 수 있습니다.

또한 "parentController"를주의 깊게 살펴보면 출시되지 않을 수도 있습니다. 그것을 nil로 설정해야합니다.

+0

리사이클링은 잘 작동하는 것 같습니다 : 4 셀이 생성됩니다 (4 셀이 화면에 표시되어 있기 때문입니다) 그리고 나서 모두 재활용됩니다. 그러나 이전 뷰로 돌아가서 목록을 다시 표시하면 4 개의 새로운 셀을 볼 수 있습니다. 생성 된 세포. 그래서 내가 계속해서 메모리 사용량을 늘릴 것인가? – Alexis

+0

현재의 경우 어떻게해야합니까? 릴리스 또는 autorelease? 나는 그들에게 릴리즈를 호출 한 후에 ref를 만질 수 있다는 것을 제외하고는 그 차이를 실제로 얻지는 못한다 ... – Alexis

+0

(객체가 더 이상 사용되지 않으면 시스템이 당신을 위해 release 할 때) 또는 use release (다음 번에 릴리스 될 때 객체가 릴리스 될 준비가되었음을 시스템에 알릴 때) 동시에 두 가지를 사용하지 마십시오. – JOM

1

예, 분명히 autorelease 세포를 사용해야합니다. alloc] init.. dequeueReusableCellWithIdentifier은 자동 등록 된 것을 반환합니다.

관련 문제