MPMediaItemArtwork imageWithSize: утечка памяти

Когда один звонит imageWithSize: на любом MPMediaItemArtwork объект, даже после всех ссылок на связанный MPMediaItem а также UIImage были отброшены, память все еще держится так, как будто на нее захватывает магическая ссылка.

Я создал целый отдельный проект для проверки этой конкретной утечки, и я очень обеспокоен тем, что это проблема с внутренним API, и что я ничего не могу с этим поделать.

Теперь давайте разберемся со старым добрым кодом. Один контроллер представления и 3 простых шага воспроизведут эту проблему. Мой код ниже делает это:

  1. Создает массив для изображений и получает массив MPMediaItemCollection объекты (с каждой коллекцией, содержащей только одну песню, для тестирования в худшем случае)
  2. Для каждого представителя MPMediaItem в каждом MPMediaItemCollection, изображение обложки альбома генерируется с CGSize 500х500.
  3. NSTimer срабатывает через 3 секунды, что просто устанавливает все массивы, связанные с изображениями, на nil

ViewController.m:

#import <MediaPlayer/MediaPlayer.h>
#import "ViewController.h"

@interface ViewController ()

@property NSMutableArray *representativeImageArray;
@property NSMutableArray *collectionArray;

@end

@implementation ViewController

- (void)letItGo {
    self.representativeImageArray = nil;
    self.collectionArray = nil;

    NSLog(@"Let go.");
}

- (void)viewDidLoad {
    [super viewDidLoad];

    self.representativeImageArray = [[NSMutableArray alloc]init];
    self.collectionArray = [NSMutableArray arrayWithArray:[MPMediaQuery songsQuery].collections];

    for(int i = 0; i < self.collectionArray.count; i++){
        MPMediaItemCollection *collection = [self.collectionArray objectAtIndex:i];
        for(int i1 = 0; i1 < collection.count; i1++){
            MPMediaItem *representativeItem = [collection representativeItem];
            UIImage *image = [representativeItem.artwork imageWithSize:CGSizeMake(500, 500)];
            if(image){
                [self.representativeImageArray addObject:image];
            }
        }
    }

    [NSTimer scheduledTimerWithTimeInterval:3.0
                                     target:self
                                   selector:@selector(letItGo)
                                   userInfo:nil
                                    repeats:NO];

    NSLog(@"Got %ld items for collectionArray (%ld images).", self.collectionArray.count, self.representativeImageArray.count);
}

@end

Для 1210 изображений, сгенерированных из 1214 элементов (размером 500x500), ниже приведен график использования памяти:

Использование памяти для 1210 изображений с imageWithSize

По сравнению с графиком использования памяти, если не вызов imageWithSize: совсем:

Теперь я видел людей, которые ранее предлагали использовать MPMediaItemArtwork"s CGSize от его bounds имущество. Итак, давайте сделаем это вместо этого.

Давай меняться

UIImage *image = [representativeItem.artwork imageWithSize:CGSizeMake(500, 500)];

в

UIImage *image = [representativeItem.artwork imageWithSize:representativeItem.artwork.bounds.size];

Теперь, после запуска того же кода, что и в ViewController.m, хотя с одним этим изменением мы получаем это для использования памяти:

Да, массивы, связанные с изображениями, были отброшены, как в предыдущих двух запусках. Несмотря на то, что память все равно колеблется около 70 МБ, и, похоже, нет способа вернуться к ~10 МБ без полного перезапуска приложения.

Это интересная проблема, с которой я боролся весь день. Лично я более привык управлять памятью, исходящей из C-фона, и зная, что все утечки памяти в основном будут моей ошибкой. Извините, если что-то здесь полностью пролетело над моей головой.

Любая помощь будет принята с благодарностью, спасибо за чтение!

0 ответов

Другие вопросы по тегам