UIImagePickerController - 枚举时集合发生突变

Posted

技术标签:

【中文标题】UIImagePickerController - 枚举时集合发生突变【英文标题】:UIImagePickerController - Collection mutated while being enumerated 【发布时间】:2011-10-07 17:32:11 【问题描述】:

当您滚动 UIImagePickerController 弹出框(PhotoLibrary 或 PhotosAlbum 种类)时,我的 iPad 应用程序崩溃。我在相册中有大约 130 张图像,当您滚动列表以显示其他缩略图时会发生崩溃。我在 ios 2.x here 的模拟器中发现了一些关于 UIImagePicker 问题的其他提及,但这似乎并不相关。这是崩溃报告:

2011-10-07 11:18:17.309 Experiences[1419:707] *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x343fe0> was mutated while being enumerated.(
    "<PLImageTableSegment: 0x343fc0>",
    "<null>",
    "<null>",
    "<PLImageTableSegment: 0x343fc0>",
    "<PLImageTableSegment: 0x343fc0>",
    "<PLImageTableSegment: 0x343fc0>",
    "<PLImageTableSegment: 0x343fc0>",
    "<PLImageTableSegment: 0x343fc0>",
    "<PLImageTableSegment: 0x343fc0>",
    "<PLImageTableSegment: 0x343fc0>",
    "<PLImageTableSegment: 0x343fc0>",
    "<PLImageTableSegment: 0x343fc0>"
)'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x319b864f __exceptionPreprocess + 114
    1   libobjc.A.dylib                     0x34af4c5d objc_exception_throw + 24
2   CoreFoundation                      0x319b7edf __NSFastEnumerationMutationHandler   + 214
    3   libobjc.A.dylib                     0x34afb36d objc_enumerationMutation + 24
    4   CoreFoundation                      0x31922b9d -[__NSArrayM dealloc] + 80
5   CoreFoundation                      0x3191cc43 -[NSObject(NSObject) release] + 30
6   PhotoLibrary                        0x3733ba81 +[PLImageTable releaseSegmentCache] + 20
7   PhotoLibrary                        0x3732a4ed -[PLPhotoLibrary dealloc] + 116
8   CoreFoundation                      0x3191cc43 -[NSObject(NSObject) release] + 30
9   CoreFoundation                      0x3191d1a1 CFRelease + 68
10  CoreFoundation                      0x3191febb _CFAutoreleasePoolPop + 146
11  Foundation                          0x30efe1cb -[NSAutoreleasePool release] + 98
12  UIKit                               0x36f0ff0f _UIApplicationHandleEvent + 5790
13  GraphicsServices                    0x35a10e77 PurpleEventCallback + 666
14  CoreFoundation                      0x3198fa97 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26
15  CoreFoundation                      0x3199183f __CFRunLoopDoSource1 + 166
16  CoreFoundation                      0x3199260d __CFRunLoopRun + 520
17  CoreFoundation                      0x31922ec3 CFRunLoopRunSpecific + 230
18  CoreFoundation                      0x31922dcb CFRunLoopRunInMode + 58
19  GraphicsServices                    0x35a1041f GSEventRunModal + 114
20  GraphicsServices                    0x35a104cb GSEventRun + 62
21  UIKit                               0x36f3ad69 -[UIApplication _run] + 404
22  UIKit                               0x36f38807 UIApplicationMain + 670
23  Experiences                         0x00002e77 main + 82
24  Experiences                         0x00002e20 start + 40
)
terminate called after throwing an instance of 'NSException'

下面是调用 UIImagePickerController 弹出框的代码:

- (void)showImagePickerForSourceType:(UIImagePickerControllerSourceType)sourceType

    if ([self.cameraPopoverViewController isPopoverVisible]) 
        DLog(@"requesting cameraPopover dismissal");
        [self.cameraPopoverViewController dismissPopoverAnimated:YES];
    

    // Set up the imagePicker common parameters
    UIImagePickerController* imagePicker    = [[UIImagePickerController alloc] init];
    imagePicker.delegate                    = self;
    imagePicker.mediaTypes                  = [NSArray arrayWithObjects:(NSString *) kUTTypeImage, nil];
    imagePicker.allowsEditing               = YES;
    imagePicker.sourceType                  = sourceType;
    DLog(@"imagePicker %@", imagePicker);

    self.newMedia = NO;

    switch (imagePicker.sourceType) 
        case UIImagePickerControllerSourceTypeCamera: 
            [self presentModalViewController:imagePicker
                                    animated:YES];
            self.newMedia = YES;
            break;
        
        case UIImagePickerControllerSourceTypePhotoLibrary: 
            // These two cases are identical, just fall through into PhotosAlbum case...
        case UIImagePickerControllerSourceTypeSavedPhotosAlbum: 
            if (self.pickerPopoverViewController) 
                // Should never occur if pickers are getting dismissed properly...
                ALog(@"had a stranded pickerPopover!");
                self.pickerPopoverViewController = nil;
            
            pickerPopoverViewController = [[UIPopoverController alloc] initWithContentViewController:imagePicker];
            // Set up the rect from which the popover should hang
            CGRect popoverRect = [cameraBtn convertRect:cameraBtn.bounds
                                                 toView:self.view];
            // ...and display the popover "hanging" from the cameraBtn
            [self.pickerPopoverViewController presentPopoverFromRect:popoverRect
                                                              inView:self.view 
                                            permittedArrowDirections:UIPopoverArrowDirectionUp
                                                            animated:YES];            
            break;
        

        default:
            break;
    
    [imagePicker release];

在我看来,一些图像/图像缩略图正在被释放(并因此改变了集合)。但我不知道该怎么办......

【问题讨论】:

【参考方案1】:

我刚遇到类似的问题。 通过反复试验,我发现如果您使用 UIImagePickerControllerSourceTypePhotoLibrary 作为 imagepicker 的源类型,它会正常工作。 但是使用 UIImagePickerControllerSourceTypeSavedPhotosAlbum 会导致应用崩溃。

【讨论】:

感谢您的帮助 - 这是我针对 iOS 4.x 的解决方法。看来 Apple 可能已经解决了 iOS 5 中的问题(我猜对 iCloud Photostreaming 进行了大改写)。

以上是关于UIImagePickerController - 枚举时集合发生突变的主要内容,如果未能解决你的问题,请参考以下文章

UIImagePickerController、自定义 UIButton 和 AutoLayout

UIImagePickerController 实况照片

OCMock 模拟 UIImagePickerController

UIImagePickerController 图像没有改变

无法弹出 UIImagePickerController

为啥 UIImagePickerController 不能推入导航栈?