Подтвердить что ты не робот

IOS 7 UIImagePickerController имеет черный превью

У меня есть UIImagePickerController, вызываемый с камерой sourceType и 80% времени, когда я получаю черный предварительный просмотр. Если я подожду, скажем, около 30 секунд, я получаю хороший предварительный просмотр, и он будет полезен примерно в 50% случаев, тогда он может снова сломаться.

Изображение, о котором идет речь, очень похоже на это. Камера iDevice показывает черный вместо предварительного просмотра

Другие люди подразумевают, что GCD может вызвать некоторые проблемы с камерой, и что обновление пользовательского интерфейса при загрузке сборщика изображений прерывает его. Я помещаю блокировку на каждый блок 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: Снимок снимка, который не был отображен, приводит к пустым моментальным снимкам. Убедитесь, что ваше представление было просмотрено как минимум один раз перед моментальным снимком или моментальным снимком после обновлений экрана.

Это показывает ВСЕГДА, когда я пытаюсь открыть контроллер выбора, но он показывает его, даже если камера правильно отображает предварительный просмотр. Я не думаю, что ошибка здесь, но это также сильно меня беспокоит.

4b9b3361

Ответ 1

Кажется, что нет хорошего ответа на это в любом месте в Интернете, поэтому мне пришлось пробиться через это сам, чтобы понять это.

Я использую ARC (как, наверное, большинство других в наши дни), поэтому ответ выше не помог мне.

Эта проблема с черными камерами возникает как побочный эффект от того, что вы делаете материал UIKit из основного потока на iOS 7. В целом, операции с UIKit в фоновом режиме приводят к появлению всяких странных вещей, происходящих на iOS 7 (память не освобождается быстро, странная производительность а также проблемы с черной камерой).

Чтобы предотвратить это, вам не нужно делать НИКАКИЕ вещи UIKit в потоках фона.

Вещи, которые вы не можете сделать для фоновых потоков: - Выделить/инициализировать UIView и подклассы - Изменить UIViews и подклассы (например, установить фрейм, установить атрибуты .image/.text и т.д.).

Теперь проблема с этим материалом в основном потоке заключается в том, что он может испортить производительность пользовательского интерфейса, поэтому вы видите все эти решения для загрузки "iOS 6", которые НЕ работают оптимально на iOS 7 (т.е. вызывая проблема черной камеры, между прочим).

Есть две вещи, которые я сделал, чтобы зафиксировать производительность, предотвращая вредные эффекты фоновых операций UIKit: - Предварительно создайте и инициализируйте все UIIмаги на фоновом потоке. Единственное, что вы должны делать с UIImages в основном потоке, это установить "imageView.image = preloadedImageObject;" - Повторно использовать представления, когда это возможно. Выполнение [[UIView alloc] init] в основном потоке может быть проблематичным, если вы делаете это в cellForRowAtIndex или в другой ситуации, когда отзывчивость является очень важной.

Удачи! Вы можете проверить, как вы это делаете, контролируя использование памяти во время работы вашего приложения. Предыстория UIKit = > быстрое наращивание использования памяти.

Ответ 2

Во время одного из моих недавних проектов у меня была такая же (или аналогичная) проблема, а именно просмотр камеры, показывающий черный экран при использовании UIImagePickerController на iOS7 (iPad).

Я обнаружил, что GCD сам по себе не является проблемой. Проблема возникает, когда вы пытаетесь использовать что-либо вообще из рамки UIKit в потоке, отличном от основного потока (как часть NSOperation).

Прежде всего, позвольте мне начать с того, что мне ясно, что вы не должны этого делать для начала. Однако в моем конкретном случае у меня не было выбора. Поскольку я думаю, что есть хорошая вероятность, что другие люди могут испытывать такое же странное поведение камеры UIImagePickerController по той же причине, я составил очень простой пример кода, объясняющий, что происходит.

Вы можете найти его здесь: https://github.com/idamediafoundry/CameraTest

В ViewController отображаются две простые кнопки. Один вызывает UIImagePickerController, показывающий камеру, а другой запускает некоторые операции GCD, выполняя простую задачу. Если вы просто открываете камеру, все работает нормально. Если вы сначала запустите операции, а затем откройте камеру, появится проблема черного предварительного просмотра.

Опять же, вы не должны называть UIKit ничем, кроме основного потока. Но я не думаю, что это нормально, что нарушение этого правила заставляет камеру работать с ошибкой при открытии ее позже в основном потоке как часть совершенно другого потока, верно?

Надеюсь, что это поможет.

Ответ 3

У меня была такая же проблема, но приложение никогда не показывало бы предупреждение о предоставлении разрешения на доступ к фотографиям, и оно никогда не появится в настройках → Конфиденциальность → Фотографии, как запросив разрешение. Он просто отобразит черный экран без подсказки разрешения.

Я, наконец, проследил это до info.plist.

введите описание изображения здесь

Как оказалось, если вы добавите ключ "Отображаемое имя Bundle" в info.plist и оставьте значение пустым, предупреждение о предупреждении никогда не будет отображаться. Кажется, предупреждение о разрешении выводит это значение для отображения в предупреждении, и если вы оставите его пустым, он просто не отобразит предупреждение.

Если у вас есть это в вашем plist без значения, это может вызвать черный предварительный просмотр.

EDIT: я столкнулся с этой проблемой с некоторыми устройствами, а не с другими, с моим тестированием всех трех устройств iPhone 6, с которыми я тестировал, и iPhone 5s не будет показывать предупреждение и будет висеть на черном экране. IPhone 4s и iPhone 6S + показали предупреждение и работали, как ожидалось.

Ответ 4

Во-первых, эта проблема кажется частично ошибкой Apple и разработчиками, вероятно, больше на стороне разработчиков. Я смог получить мое приложение для создания черного изображения предварительного просмотра, переключаясь между собственным приложением камеры и моим собственным использованием приложения в режиме UIImagePickerController камеры. Это было непротиворечиво, но я делал это, повторяя эти шаги несколько раз в течение 5-15 раз, в конечном итоге это станет черновым превью.

С другой стороны, я смог решить эту проблему, реорганизовывая свой собственный код. Мне не нужно было создавать пользовательскую камеру, как это делали другие, с AVFoundation, скорее, я удалил все потенциальные/допустимые утечки памяти из моего кода. Убедитесь, что вы тестируете приложение с помощью инструментов, избавляетесь от каких-либо утечек. Очистка UIImagePickerController также может отличаться в зависимости от использования ARC или нет. После моего рефактора проблема с черным предварительным просмотром исчезла. Я считаю, что утечка памяти в вашем приложении - это то, что вызывает предварительный просмотр видео после того, как он когда-нибудь станет черным.

И последнее, но не менее важное: у меня было другое приложение, в котором используется сканер zxing, который использует AVFoundation для декодирования изображений из потока предварительного просмотра в прямом эфире... это было очень сложно исправить, это был ARC, смешанный с не-дугой (zxing non- дуги). Мне пришлось реорганизовать кучу большего кода, поскольку иерархия view/ UIViewController была намного сложнее, и ключом был получить фактический объект, который содержит сеанс AVFoundation для dealloc. После дня рефакторинга эта проблема исчезла, так что да, подключение утечек памяти было ответом в обоих случаях проблемы предварительного просмотра черного изображения в iOS 7.

Ответ 5

прежде всего проверьте, имеет ли ваше приложение разрешение на доступ к камере или нет. Я думаю, что вы нажали "нет" в первый раз, когда камера запускается в приложении. Теперь сделайте одно. перейдите в "Настройки" - "Конфиденциальность" → "Камера", затем выберите свое приложение, проверьте, включено ли его включение, если оно выключено. Теперь вы можете получить доступ к камере в приложении.

Ответ 6

Похоже, это проблема iOS 7. Даже я столкнулся с аналогичной ситуацией, когда я загружаю фотографию из галереи изображений из своего приложения, а затем пытаюсь открыть черный экран камеры.

Ответ 7

В моем случае мне пришлось переместить некоторые методы в основной поток.

Мое приложение создает новое изображение с новым контекстом, я могу создать новый контекст в другом потоке и использовать функции 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);

Также мне пришлось переместить в основной поток все объекты объектов пользовательского интерфейса, например:

    __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
});

Надеюсь, это поможет:)