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: Снимок снимка, который не был отображен, приводит к пустым моментальным снимкам. Убедитесь, что ваше представление было просмотрено как минимум один раз перед моментальным снимком или моментальным снимком после обновлений экрана.
Это показывает ВСЕГДА, когда я пытаюсь открыть контроллер выбора, но он показывает его, даже если камера правильно отображает предварительный просмотр. Я не думаю, что ошибка здесь, но это также сильно меня беспокоит.
Ответы
Ответ 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
});
Надеюсь, это поможет:)