2015-03-02 4 views
0

Я показываю около 50 изображений. В представлении прокрутки, и я столкнулся с проблемой памяти, каждый раз, когда контроллер загружает использование памяти, увеличивается, и она превышает 200 МБ в приложении Instruments.UIImageView - Memory Issue

.h файл из моего пользовательского класса #import

@class AnimalGrid; 

@protocol AnimalGridViewDelegate <NSObject> 
-(void)animalGrid:(AnimalGrid*)animalgridview tappedAtIndex:(int)index andName:(NSString*)animalName; 
@end 

@interface AnimalGrid : UIView 

@property(nonatomic, strong) UIImage   *animalImage; 
@property(nonatomic, copy)  NSString  *animalName; 
@property(nonatomic) int  animalTag; 

@property (nonatomic, assign) id <AnimalGridViewDelegate> Delegate; 

-(id)initGridWithFrame:(CGRect)frame andAnimalImage:(UIImage*)image andAnimalName:(NSString*)animalname andTag:(int)tag; 
-(void)setFont:(UIFont*)font; 
@end 

.m файл моего пользовательского класса

#import "AnimalGrid.h" 

@implementation AnimalGrid 
{ 
    UIImageView *_contentView; 
    UILabel  *_accessoryView; 
    UIImage  *displayImage; 
    NSString  *displayText; 
} 

@synthesize Delegate = _Delegate; 

-(id)initGridWithFrame:(CGRect)frame andAnimalImage:(UIImage*)image andAnimalName:(NSString*)animalname andTag:(int)tag 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 

     self.backgroundColor = [UIColor clearColor]; 
     self.animalName = animalname; 
     self.animalTag = tag; 
     displayImage = image; 
     displayText = animalname; 
     CGFloat contentHeight = frame.size.height * 0.8; 

     if (animalname == nil || animalname.length == 0) 
      contentHeight = frame.size.height; 

     CGFloat margin = 0; 
     if (displayImage.size.height < contentHeight) 
     { 
      margin = contentHeight - displayImage.size.height; 
     } 


     UIView *placeholderView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, contentHeight)]; 
     placeholderView.backgroundColor = [UIColor clearColor]; 
     if (image.size.height > placeholderView.frame.size.height) 
     { 
      _contentView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, placeholderView.frame.size.height)]; 
     }else if (image.size.height < placeholderView.frame.size.height){ 

      CGFloat margin = placeholderView.frame.size.height - image.size.height; 
      _contentView = [[UIImageView alloc]initWithFrame:CGRectMake(0, margin, frame.size.width, placeholderView.frame.size.height - margin)]; 

     } 

     _contentView.backgroundColor = [UIColor clearColor]; 
     _accessoryView = [[UILabel alloc]initWithFrame:CGRectMake(0, frame.size.height * 0.7, frame.size.width, frame.size.height-frame.size.height * 0.7)]; 
     _accessoryView.numberOfLines = 2; 
     _accessoryView.backgroundColor = [UIColor clearColor]; 
     _accessoryView.font = [UIFont fontWithName:@"HFFAirApparent" size:23]; 
     _accessoryView.textColor = [UIColor orangeColor]; 

     [placeholderView addSubview:_contentView]; 
     [self addSubview:placeholderView]; 

     if (animalname != nil || animalname.length > 0) 
     [self addSubview:_accessoryView]; 

     if(image) 
      _contentView.image = image; 

     _contentView.contentMode = UIViewContentModeScaleAspectFit; 
     _accessoryView.text = animalname; 
     _accessoryView.numberOfLines = 0; 
     [_accessoryView sizeToFit]; 

     CGFloat w = self.bounds.size.width/2; 
     _accessoryView.frame = CGRectMake(w - (_accessoryView.frame.size.width/2), _accessoryView.frame.origin.y, _accessoryView.frame.size.width, _accessoryView.frame.size.height); 

     UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapedOnImage:)]; 
     singleTap.numberOfTapsRequired = 1; 
     singleTap.numberOfTouchesRequired = 1; 

     [_contentView addGestureRecognizer:singleTap]; 
     _contentView.userInteractionEnabled = YES; 
     self.userInteractionEnabled = YES; 
    } 

    return self; 
} 

-(void)setFont:(UIFont*)font 
{ 
    _accessoryView.font = font; 
} 


-(void)tapedOnImage:(id)sender 
{ 
    if ([_Delegate respondsToSelector:@selector(animalGrid:tappedAtIndex:andName:)]) { 
     [_Delegate animalGrid:self tappedAtIndex:self.animalTag andName:self.animalName]; 
    } 
} 

@end 

И это, как я создаю объект моего пользовательского класса и показ их над списком прокрутки. В моем файле контроллера я использую следующие методы:

-(void)setGridAnimals 
{ 
    @try { 
     [self creatingGridsWithCompletion:^(BOOL done, NSMutableArray *arr) 
     { 
      for (int i = 0; i < arr.count; i++) 
      { 
       UIView *gView = [arr objectAtIndex:i]; 
       [gridScrollView addSubview:gView]; 
      } 
      gridScrollView.scrollEnabled = YES; 
      gridScrollView.pagingEnabled = YES; 
      gridScrollView.bounces = YES; 
      gridScrollView.contentSize = CGSizeMake(gridScrollView.frame.size.width, gridScrollView.frame.size.height*arr.count); 
      [aView hideIndicatorView:YES]; 
     }]; 
    } 
    @catch (NSException *exception) { 
     NSLog(@" Exception is = %@ ",exception.description); 
    } 
    @finally { 

    } 


} 


-(void)creatingGridsWithCompletion:(completionBlock)complete 
{ 
    @autoreleasepool { 
     NSMutableArray *pageArray = [NSMutableArray new]; 
     int rowcount = 3; 
     int columncount = 5; 

     CGFloat width = gridScrollView.frame.size.width/columncount - 5; 
     CGFloat height = gridScrollView.frame.size.height/rowcount - 5; 

     int pagecount = gridAnimalArray.count/(rowcount*columncount); 

     if (gridAnimalArray.count%(rowcount*columncount)) 
     { 
      pagecount += 1; 
     } 
     //pagecount = 1; 
     int x = 0; 
     for (int i = 0; i < pagecount; i++) 
     { 
      UIView *page = [[UIView alloc]initWithFrame:CGRectMake(0, x, gridScrollView.frame.size.width, gridScrollView.frame.size.height)]; 
      for (int j = 0; j < rowcount; j++) 
      { 
       for (int k = 0; k < columncount; k++) 
       { 
        int tag = (i*(rowcount*columncount))+(j*columncount)+k+1; 
        if (tag > gridAnimalArray.count) 
        { 
         break; 
        } 
        YEAnimal *animal = [gridAnimalArray objectAtIndex:tag-1]; 
        NSString *name = [[animal.GridName componentsSeparatedByString:@"."] objectAtIndex:0]; 
        UIImage *gridImg; 
        if ([[NSFileManager defaultManager]fileExistsAtPath:[[NSBundle mainBundle] pathForResource:name ofType:@"png"]]) 
        { 
         NSString * imgpath= [ [ NSBundle mainBundle] pathForResource:name ofType:@"png"]; 
         gridImg=[UIImage imageWithContentsOfFile: imgpath]; 
        }else if ([[NSFileManager defaultManager]fileExistsAtPath:[[NSBundle mainBundle] pathForResource:name ofType:@"jpg"]]) 
        { 
         NSString * imgpath= [ [ NSBundle mainBundle] pathForResource:name ofType:@"jpg"]; 
         gridImg=[UIImage imageWithContentsOfFile: imgpath]; 
        } 

        AnimalGrid *grid = [[AnimalGrid alloc]initGridWithFrame:CGRectMake((k * width)+5, (j*height), width, height) andAnimalImage:gridImg andAnimalName:animal.SpeciesName andTag:tag]; 
        grid.backgroundColor = [self getColor]; 
        [grid setDelegate:self]; 
        [page addSubview:grid]; 
       } 
      } 

      [pageArray addObject:page]; 
      x += gridScrollView.frame.size.height; 
     } 

     complete(YES,pageArray); 
    } 
} 

Вот как выглядит сетка: http://s17.postimg.org/x9xdfl4j3/i_OS_Simulator_Screen_Shot_Mar_3_2015_1_54_45_P.png

Так далеко я узнал, что я должен использовать [UIImage imageWithContentsOfFile:] вместо [UIImage imageNamed:], чтобы загрузить изображение, но все же это не помогает мне.

Есть ли способ, что я могу освободить память, выпустив ImageViews

Спасибо.

+0

Добро пожаловать в переполнение стека. Ожидается, что загрузка 50 изображений займет столько памяти. Есть ли конкретная проблема, которую вы пытаетесь решить? Что вы пробовали? –

ответ

0

Возможны несколько апробаций, в зависимости от расположения вашего вида. Как это выглядит?

Однако вы можете использовать таблицу для отображения изображений или использования коллекции. На самом деле для этого создана коллекция.

Если вы хотите придерживаться вида прокрутки, то эти 50 видов едва заметны сразу. Фактически вы можете установить их изображения перед тем, как каждое представление появится в поле зрения, и удалите изображения (установите изображение на ноль), когда представление перемещается за пределы экрана.

Приложение, которое я сделал повторно, сконструировано таким образом, что на экране отображается только одно и точно одно из изображений. Когда пользователь прокручивает изображение соседа, он появляется в поле зрения. (пейджинговый механизм) На мой взгляд, количество возможных просмотров непредсказуемо. Хотя это тоже возможно с коллекцией, я пошел на просмотр прокрутки. В этой точке зрения я разработал вид прокрутки хостинга таким образом, чтобы он был достаточно большим, чтобы удерживать три вида. Средний вид их виден на экране. (Какие исключения применяются при отображении самого первого или последнего - если есть). Когда пользователи прокручиваются достаточно далеко, чтобы вид соседа был полностью видимым, я возвращаю scrollview так, чтобы его средняя была видна снова, переместите вид в середину, которая только что стала видимой, переместите видимое ранее вид на внешний конец и заполните другой входящий конец новым представлением. Это позволяет бесконечной прокрутке без необходимости хранить более 4 изображений в памяти одновременно. (4: тот, который только что переместился, два, которые сдвинуты в пределах прокрутки, а новые - по одному и тому же методу за раз).

+0

Привет, я добавил ссылку, чтобы показать вам, как выглядит моя сетка. Я выполнил ваши инструкции и теперь загружаю только видимые изображения в ScrollView и когда пользователь прокручивает вверх или вниз. Я удаляю предыдущие объекты и создаю следующий набор объектов показывать. Это, несомненно, уменьшило давление памяти, но все равно использование памяти увеличивается каждый раз, когда контроллер загружается, хотя приращение очень низкое. –

+0

Теперь, когда вы добавили ссылку на макет, я бы предложил вместо этого посмотреть коллекцию.Он поставляется с множеством услуг, которые вам нужны, например. он предоставляет вам возможность повторно использовать ячейки (и, следовательно, изображения), и он заботится о создании ячеек (и, следовательно, изображений) только для тех, которые в настоящее время видны. –