UIImagePickerController mediaTypes kUTTypeMovie causes small memory leak in NSCFNumber

marshn picture marshn · Aug 16, 2011 · Viewed 13.2k times · Source

Xcode 4.0.2
iPhone4 iOS 4.3.5
CoreLocation and MobileCoreServices frameworks are implemented.
imported MobileCoreServices/UTCoreTypes.h

- (void) displayVideoPicker
{
    UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
    ipc.sourceType =  UIImagePickerControllerSourceTypePhotoLibrary;
    ipc.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil];
    ipc.videoMaximumDuration = 45.0f;
    ipc.videoQuality = UIImagePickerControllerQualityTypeMedium;
    ipc.delegate = self;
    [self presentModalViewController:ipc animated:YES];
    [ipc release];
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    [[picker parentViewController] dismissModalViewControllerAnimated: YES];
}

Instruments is reporting small 16 Bytes leaks on NSCFNumber, possible Frame FigRemote_CreatePropertyListFromBinaryPListData:

Leaked Object   #   Address Size    Responsible Library Responsible Frame
NSCFNumber,8        128 Bytes   MediaToolbox FigRemote_CreatePropertyListFromBinaryPListData

If I remove this line the leak goes away:

ipc.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil];

I've tried this and it didn't get rid of the leak.

NSArray *myMediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil];
ipc.mediaTypes = myMediaTypes;
[myMediaTypes release];

The leak occurs just after picking the video and returning to the initial view. Any thoughts?

Answer

themacolyte picture themacolyte · Jan 13, 2012

I'm getting a couple of leaks around the UIImagePickerController and this was one of them. Total leak was 208 bytes. I found that if the media types are specified using CoreFoundation C code, this leak goes away.

So the following code leaks:

imagePickerController.mediaTypes = [NSArray arrayWithObjects:(NSString*)kUTTypeImage, (NSString*)kUTTypeMovie, nil];

Can be replaced by the following code which does not cause the same leak:

CFStringRef mTypes[2] = { kUTTypeImage, kUTTypeMovie };

CFArrayRef mTypesArray = CFArrayCreate(CFAllocatorGetDefault(), (const void**)mTypes, 2, &kCFTypeArrayCallBacks);

imagePickerController.mediaTypes = (NSArray*)mTypesArray;

CFRelease(mTypesArray);

My theory is that the leaking statement is not providing the information that the final argument of the working code provides. kCFTypeArrayCallBacks provides the CFArray created with the information it needs to properly retain and release the objects it contains (using CFRetain and CFRelease). These objects it contains are CFStringRefs... The leaking statement casts these CFStringRefs to NSStrings and I think the NSArray is using Objective-C standard retain and release messages on its objects.

This theory would seem to be bogus because CFArray and NSArray are toll-free bridged and it should "just work". I'm sticking with it for now though - it's the only significant difference between the two code snippets above that jumps out at me.