【问题标题】:iOS 7 UIImagePickerController has black previewiOS 7 UIImagePickerController 有黑色预览
【发布时间】:2013-09-29 18:29:25
【问题描述】:

我有一个 UIImagePickerController 被 sourceType 相机调用,并且 80%​​ 的时间我得到一个黑色预览。如果我等待,比如说大约 30 秒,我会得到一个很好的预览,大约 50% 的时间会很好,然后它会再次中断。

有问题的图像与此非常相似。 iDevice camera shows black instead of preview

其他人暗示 GCD 可能会导致相机出现一些问题,并且在加载图像选择器时更新 UI 会破坏它。为此,我在每个调用主线程的 GCD 块上都加了锁。

这是一个旋转图像以模拟活动指示器的示例。

-(void)animateLoadingImage {

if (isMainThreadBlocked) {
    return;
}

self.radians += M_PI_4 / 2;
[UIView beginAnimations:@"progress rotation" context:nil];
[UIView setAnimationDuration:.1];
self.loadingImageView.transform = CGAffineTransformMakeRotation(self.radians);
[UIView commitAnimations];


}

PS:对尚未渲染的视图进行快照会导致快照为空。确保您的视图在快照之前或屏幕更新后的快照之前至少渲染过一次。

当我尝试打开选择器控制器时,它总是显示,但即​​使相机正确显示预览,它也会显示它。我不认为错误就在这里,但这也让我很烦恼。

【问题讨论】:

  • 你弄明白了吗?
  • 不,最后我确实有一些猜测,也许这个项目是以前的 iOS6 然后 iOS7 有一些麻烦,但如果我想我似乎无法重现这个问题......解决的关键这是使用 AVFoundation 实现自己的相机
  • 我提交了错误报告。我会及时向大家发布。 AVFoundation 向我显示了相同的结果。
  • 如果预览适用于某些设备,但不适用于其他设备 - 请注意来自 digitalHound 的 this answer,它拯救了我的一天!

标签: iphone uiimagepickercontroller ios7


【解决方案1】:

在我最近的一个项目中,我遇到了同样(或类似)的问题,即在 iOS7 (iPad) 上使用 UIImagePickerController 时相机预览显示黑屏。

我发现 GCD 本身不是问题。当您尝试在主线程以外的线程(作为 NSOperation 的一部分)中使用 UIKit 框架中的任何内容时,就会出现问题。

首先,让我先说,我很清楚你不应该一开始就这样做。然而,在我的具体情况下,我别无选择。由于我认为其他人很有可能遇到同样奇怪的 UIImagePickerController 相机行为,原因相同,所以我编写了一些非常简单的示例代码来解释发生了什么。

你可以在这里找到它:https://github.com/idamediafoundry/CameraTest

ViewController 显示了 2 个简单的按钮。一个调用 UIImagePickerController,显示相机,另一个启动一些 GCD 操作做一个简单的任务。如果您只是打开相机,一切正常。如果先开始操作再打开相机,就会出现预览黑屏的问题。

同样,您不应该在主线程之外的任何地方调用 UIKit。但是我认为打破这个规则会导致相机在稍后在主线程中作为完全不同流程的一部分打开时出现故障是不正常的,对吧?

希望这会有所帮助。

【讨论】:

  • 这似乎是原因......可以把这个给苹果开发人员吗?,他们要求一个示例项目
  • 好的,你能把github repo的链接发给他们吗?
  • 我想知道在这个代码/方法中是否还有一些我们可以做的事情来规避这个问题。
  • 道具给你,我会发送项目(需要信用的地方;))
  • 在我的情况下,我在后台线程中更新 UITextField 的文本。将其移出线程解决了这个问题。
【解决方案2】:

网上的任何地方似乎都没有一个好的答案,所以我不得不自己费力地解决这个问题。

我正在使用 ARC(可能像现在大多数其他人一样),所以上面的答案并没有真正帮助我。

这个黑色摄像头问题是在 iOS 7 上从主线程中执行 UIKit 操作的副作用。总的来说,后台 UIKit 操作会导致 iOS 7 上发生各种奇怪的事情(内存没有被及时释放,奇怪的性能故障和黑色摄像头问题)。

为了防止这种情况,你不需要在后台线程上做任何 UIKit 的事情。

你不能在后台线程上做的事情: - 分配/初始化 UIViews 和子类 - 修改 UIView 和子类(例如,设置框架、设置 .image/.text 属性等)。

现在,在主线程上做这些事情的问题是它会扰乱 UI 性能,这就是为什么你会看到所有这些 iOS 6“后台加载”解决方案在 iOS 7 上不能以最佳方式工作(即,导致黑色摄像头问题等)。

我做了两件事来修复性能,同时防止后台 UIKit 操作的不良影响: - 在后台线程上预先创建和初始化所有 UIImage。您应该在主线程上使用 UIImages 做的唯一事情是设置“imageView.image = preloadedImageObject;” - 尽可能重复使用视图。如果您在 cellForRowAtIndex 或其他响应性非常重要的情况下执行 [[UIView alloc] init],在主线程上执行此操作仍然可能会出现问题。

祝你好运!您可以通过在应用运行时监控内存使用情况来测试您的表现。背景 UIKit => 内存使用量迅速增加。

【讨论】:

  • 我一直在识别 uikit 禁止在后台使用的方法时遇到问题,所以这可能是我的问题的原因,即使我很确定没有 uikit 被修改...我会检查这个出来让你知道......问候!
  • 我看到我在下面重复回答了:) 这确实是正确的答案。
  • 这是正确的答案,对 Bart 的支持也是为了给我发送给苹果的一个项目。谢谢大家
  • 苹果反馈了吗?我仔细检查了有问题的主线程,在那里没有发现任何东西。虽然我的应用程序最多使用了 100 MB“实时字节”,但在打开相机预览时它只使用了大约 20 MB,这真的不应该太多......
  • 你确定吗?试试这个库,它会帮助你调试你是否在主线程之外尝试一些基本的 UIKit 东西。它应该在 github/google 的某个地方:PSPDFUIKitMainThreadGuard.m
【解决方案3】:

我遇到了同样的问题,但该应用永远不会显示授予访问照片权限的警报,并且它永远不会在“设置”->“隐私”->“照片”中显示为已请求许可。它只会在没有权限提示的情况下显示黑屏。

我终于找到了 info.plist。

事实证明,如果您将“捆绑显示名称”键添加到 info.plist 并将值留空,则权限警报将永远不会显示。似乎权限警报会拉取此值以显示在警报中,如果您将其留空,则根本不会显示警报。

如果你的 plist 中有这个没有值,它可能会导致黑色预览。

编辑:我在某些设备上遇到了这个问题,而在其他设备上没有遇到这个问题,我测试了我测试过的所有 3 台 iPhone 6 设备,而 iPhone 5s 不会显示警报并且会挂在黑屏上。 iPhone 4s 和 iPhone 6S+ 显示警报并按预期工作。

【讨论】:

  • 我刚刚测试了一个新的空项目,即使没有 Bundle 显示名称,相机也可以工作,如果没有 Bundle 显示名称键,则使用 Bundle 名称。而且我认为这不是 OP 的问题
  • 在运行 iOS 9.1 的 iPhone 6 上试用。 iPhone 4s 和 iPhone 6S+ 都适用于我并显示警报,而 iPhone 5s 和 6 则没有。
  • 我已经尝试过运行 iOS 9.1 的 iPhone 6,没有 Bundle 显示名称键并且可以正常工作,它显示的是 Bundle 名称
  • 如果您删除密钥是的,它可以工作,如果您添加密钥但不提供值,那就是我没有收到警报的时候。添加键但将值保留为空字符串,您应该会看到问题。
  • 您的回答对我非常有用,我花了大约 2 天的时间来解决它。谢谢朋友。
【解决方案4】:

首先,这个问题似乎部分是苹果和开发人员的错,可能更多是在开发人员方面。通过在本机相机应用程序和我自己的应用程序对UIImagePickerController 相机模式的使用之间切换,我能够让我的应用程序生成黑色预览图像。它并不一致,但我确实让它发生了重复这些步骤大约 5-15 次,最终它会变成黑色预览。

另一方面,我可以通过重构自己的代码来解决这个问题。我不需要像其他人使用 AVFoundation 那样构建自定义相机,而是从我的代码中删除了所有潜在/有效的内存泄漏。确保您使用 Instruments 测试您的应用程序,消除任何泄漏。同时清理UIImagePickerController,这可能会因是否使用ARC而有所不同。在我重构之后,黑色预览的问题就消失了。我相信您的应用程序中的内存泄漏是导致视频预览在一段时间后变黑的原因。

最后但并非最不重要的一点是,我有另一个使用 zxing 扫描仪的应用程序,它使用 AVFoundation 从实时预览流中解码图像......这个修复起来非常棘手,它是 ARC 与非弧(zxing non-弧)。我不得不重构更多代码,因为视图/UIViewController 层次结构要复杂得多,并且获取包含 AVFoundation Session 的实际对象以释放是关键。经过一天的重构,这个问题就消失了,所以是的,在我遇到 iOS 7 中黑色图像预览问题的两种情况下,堵住内存泄漏都是答案。

【讨论】:

    【解决方案5】:

    就我而言,我不得不将一些方法移至主线程。

    我的应用程序使用新上下文创建新图像,我可以在不同的线程中创建新上下文并使用 CGContext 函数(如 CGContextScaleCTM 或 CGContextTranslateCTM 或 CGContextConcatCTM)和 [uiimage drawInRect:Mybounds];。

    当我在上下文中绘制图层时,基本上我必须将 renderInContext 方法移到主线程:

    CGSize sizeView = viewPrintBase.frame.size;
    UIGraphicsBeginImageContext(sizeView);
    currentContext = UIGraphicsGetCurrentContext();
    
    dispatch_sync(dispatch_get_main_queue(), ^{
        [viewPrintBase.layer renderInContext:currentContext];
        [imageViewPhotoUser.layer renderInContext:currentContext];
        if (imageViewMask) {
            [imageViewMask.layer renderInContext:currentContext];
        }
    });
    [imageSnapShotDrawinfView drawInRect:viewPrintBase.bounds];
    UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    CGImageRef imageRef = CGImageCreateWithImageInRect([finalImage CGImage], viewPrintBase.bounds);
    // or use the UIImage wherever you like
    imageSnapShot = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    

    我还必须将所有 UI 对象的创建移至主线程,例如:

        __block UIView *viewPrintBase;
    dispatch_sync(dispatch_get_main_queue(), ^{
        viewPrintBase = [[UIView alloc]initWithFrame:CGRectMake(0, 0, WIDTH_FINAL_IMAGE, HEIGHT_FINAL_IMAGE)];
        viewPrintBase.backgroundColor = [UIColor whiteColor];
        [viewPrintBase setClipsToBounds:YES];
        //We get the photo user
    });
    

    我希望这会有所帮助:)

    【讨论】:

      【解决方案6】:

      首先检查您的应用是否有权访问相机。我认为您在相机第一次在应用中启动时按下了“否”选项。现在做一件事。转到设置->隐私->相机,然后在此处选择您的应用程序,检查其是否打开,如果关闭则打开..现在您可以在应用程序中访问相机。

      【讨论】:

        【解决方案7】:

        似乎这是 iOS 7 的问题。甚至我也遇到过类似的情况,当我从我的应用程序中从图片库上传照片,然后尝试打开相机时出现黑屏。

        【讨论】:

        • 我使用 AVFoundation 解决了这个问题并手动创建了一个相机应用程序......我向苹果报告了这个错误并得到了回复,要求我创建一个可以显示这种行为的项目......问题是...我不知道为什么会这样,所以很难复制这个问题...
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多