Search code examples
iosobjective-cmemory-managementinstruments

MPMediaItemPropertyArtwork causes crash (weird issue)


allocations before running 'extra loop' allocations before running 'crashing' loop

The code:

// loading items to the array, there are no memory warnings after this is completed. The first allocations screenshot is after this code and before extra loop code.
NSMutableArray *albumCovers = [[NSMutableArray alloc] init];
for (MPMediaQuery *query in queries) {
    NSArray *allCollections = [query collections];
    for (MPMediaItemCollection *collection in allCollections) {
        MPMediaItemArtwork *value = [collection.representativeItem valueForProperty:MPMediaItemPropertyArtwork];
                UIImage *image = [value imageWithSize:CGSizeMake(100, 100)];
                if (image) {
                    [albumCovers addObject:image];
                }
            }
        }
    }
    _mediaCollections = [NSArray arrayWithArray:artworkedCollections];
    _albumCovers = [NSArray arrayWithArray:albumCovers];
}

And somewhere else:

// !!!!! extra loop - from here the memory starts to grow and never release
for (i=0; i< 800; i++) {
    UIImage * coverImage = [_albumCovers objectAtIndex:indexPath.row];
    [veryTemp setImage:coverImage]; // exactly this line adds to the memory. with this line commented, there is no problem.
}

allocations after running 'extra loop' allocations before running 'crashing' loop

and to clarify, call stack with only-obj-c on and system libraries off (if i turn them on, the highest % is 0.9% per heaviest method) call stack after extra loop

I've made some research, and found at stackoverflow, that these VM:ImageIO_PNG_Data are usually comming from [UIImage imageNamed:], however as you can see i don't use this method, i'm just getting the reference from MPMediaItemCollection.


Solution

  • The problem was that UIImage usually keeps just a ref(CGImageRef), which is a small one. After displaying items, CGImageRef was 'injected' with information. As a result the table was growing all the time.

    The simple but not the most beautiful solution was to use the code:

    NSArray = @[obj1, obj2, obj3]; // where obj is custom NSObject and has a UIImage property
    

    instead of:

    NSArray = @[img1, img2, img3]; // where img is of UIImage type