【问题标题】:UIImagePickerController mediaTypes kUTTypeMovie causes small memory leak in NSCFNumberUIImagePickerController mediaTypes kUTTypeMovie 导致 NSCFNumber 中的小内存泄漏
【发布时间】:2011-10-27 15:19:37
【问题描述】:

Xcode 4.0.2
iPhone4 iOS 4.3.5
实现了 CoreLocation 和 MobileCoreServices 框架。
导入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 报告 NSCFNumber 上的 16 字节小泄漏,可能是帧 FigRemote_CreatePropertyListFromBinaryPListData

Leaked Object # Address Size 责任库责任框架 NSCFNumber,8 128 Bytes MediaToolbox FigRemote_CreatePropertyListFromBinaryPListData

如果我删除这条线,泄漏就会消失:

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

我已经尝试过了,但它并没有消除泄漏。

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

在选择视频并返回初始视图后发生泄漏。有什么想法吗?

【问题讨论】:

  • 为什么要将常量转换为字符串?不看文档..这似乎是不必要的
  • 哦,我明白了..在想这个常量可能是一个原始的,但它是一个 CFStringRef ......嗯......好吧,它的 16 个字节,老实说它并不重要,它从哪里发生当它在内部从二进制 plist 创建 plist 时,它看起来像一个 Apple 错误
  • @marshn 这两个答案中的任何一个是否可以帮助您解决问题?请选择其中一个作为您接受的答案。

标签: iphone memory memory-leaks uiimagepickercontroller xcode-instruments


【解决方案1】:

我在UIImagePickerController 周围发现了一些漏洞,这就是其中之一。总泄漏量为 208 字节。我发现如果使用CoreFoundation C 代码指定媒体类型,这种泄漏就会消失。

所以下面的代码泄露了:

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

可以替换为以下不会导致相同泄漏的代码:

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

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

imagePickerController.mediaTypes = (NSArray*)mTypesArray;

CFRelease(mTypesArray);

我的理论是泄漏语句没有提供工作代码的最终参数提供的信息。 kCFTypeArrayCallBacks 为创建的CFArray 提供正确保留和释放它包含的对象所需的信息(使用CFRetainCFRelease)。它包含的这些对象是CFStringRefs..。泄漏的语句将这些 CFStringRefs 转换为 NSStrings,我认为 NSArray 在其对象上使用了 Objective-C 标准的保留和释放消息。

这个理论似乎是虚假的,因为CFArrayNSArray 是免费桥接的,它应该“正常工作”。不过我现在坚持使用它 - 这是上面两个代码 sn-ps 之间唯一显着的区别。

【讨论】:

    【解决方案2】:

    首先,您需要确保将MobileCoreServices Framework 包含到您的Xcode 项目中,然后是#import <MobileCoreServices/MobileCoreServices.h>,它可以让您访问预定义的媒体类型常量,例如kUTTypeImageKUTTypeMovie

    然后,您需要知道mediaType property 需要一个 array,即使它只包含一个元素。

    您放置此代码的视图控制器需要成为这两个的委托:UINavigationControllerDelegateUIImagePickerControllerDelegate

    然后你可以把这段代码放在某个地方让它被执行(就像在一个按钮动作里面):

    UIImagePickerController *camera = [[UIImagePickerController alloc] init];
    camera.sourceType = UIImagePickerControllerSourceTypeCamera;
    camera.delegate = self;
    camera.mediaTypes = @[(NSString *)kUTTypeImage, (NSString *)kUTTypeMovie];
    [self presentViewController:camera animated:YES completion:nil];
    

    另外,在我上面代码的第 4 行,上面写着camera.mediaTypes,你也可以轻松地做到这一点:

    camera.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
    

    【讨论】:

    • 代码答案应该附有解释。请详细说明如何/为何解决此问题。
    猜你喜欢
    • 1970-01-01
    • 2019-09-06
    • 2015-07-06
    • 2014-06-07
    • 2013-11-20
    • 2011-10-28
    • 2016-01-18
    • 2012-12-13
    • 1970-01-01
    相关资源
    最近更新 更多