O instantâneo do iOS 8 em uma visualização que não foi renderizada resulta em um instantâneo vazio

228

No iOS 8, estou tendo problemas para capturar imagens da câmera até agora, estou usando este código para

UIImagePickerController *controller=[[UIImagePickerController alloc] init];
controller.videoQuality=UIImagePickerControllerQualityTypeMedium;
controller.delegate=(id)self;
controller.sourceType=UIImagePickerControllerSourceTypeCamera;
[self presentViewController:controller animated:YES completion:nil];

Mas no iOS 8 eu estou conseguindo isso:

Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.

Eu tentei com a solução fornecida por este post com

@property (strong,nonatomic)UIImagePickerController *controller;

_controller=[[UIImagePickerController alloc] init];
_controller.videoQuality=UIImagePickerControllerQualityTypeMedium;
_controller.delegate=(id)self;
_controller.sourceType=UIImagePickerControllerSourceTypeCamera;
_[self presentViewController:controller animated:YES completion:nil];

e isto

...
controller.modalPresentationStyle=UIModalPresentationFullScreen;
or
controller.modalPresentationStyle=UIModalPresentationCurrentContext;
...

e isto

double delayInSeconds = 0.1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [self presentViewController:controller animated:YES completion:nil];
});

e isto

[self presentViewController:controller animated:YES completion:NULL];

e isto

[self presentViewController:controller animated:YES completion:^{

}];

qualquer ideia?

souvickcse
fonte
3
Tenho o mesmo problema e ainda mais esse bug trava meu aplicativo várias vezes. Espero que a atualização 8.0.2 corrija esse bug. Quando executo meu aplicativo no iOS7, ele funciona como um encanto, sem avisos estúpidos. Parece que o iOS 8 tem um longo caminho para a estabilidade.
NCFUSN
9
Evento com 8.0.2 atualização este problema ainda persiste
ArdenDev
2
Eu estava tendo o mesmo problema. Depois de tirar a foto, eu estava processando em outro segmento. Depois que mudei o código para o thread principal, tudo estava bem. dispatch_async(dispatch_get_main_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{dispatch_async(dispatch_get_main_queue(), ^{
mikeyq6
9
O mesmo problema acontece no iOS 8.1
Raptor
12
Também acontece no iOS 9.
Sebyddd 3/09/15

Respostas:

131

Tenho certeza de que isso é apenas um bug no iOS 8.0. É reproduzível com os aplicativos POC mais simples que não fazem nada além de tentar apresentar o UIImagePickerControllerque você está fazendo acima. Além disso, não há um padrão alternativo para exibir o seletor de imagens / câmera, que eu saiba. Você pode até baixar o aplicativo de exemplo Using UIImagePickerController da Apple , executá-lo e ele gerará o mesmo erro imediatamente .

Dito isto, a funcionalidade ainda funciona para mim. Além do aviso / erro, você tem problemas com o funcionamento do seu aplicativo?

KevinH
fonte
2
Sim, provavelmente é um bug, o código está funcionando bem para mim também.
souvickcse
4
@souvickcse Também estou encontrando esse erro. Sempre que ocorre, a visualização da imagem que aparece depois que uma nova foto é tirada fica completamente preta. No entanto, os botões "Re-Take" e "Use Photo" na parte inferior da tela ainda aparecem e funcionam corretamente. Você está testemunhando esse mesmo comportamento?
Barry Beerman
3
@souvickcse Estou usando a última linha de base do plug-in da câmera phonegap, localizada aqui: github.com/apache/cordova-plugin-camera . Tudo funciona bem com iOS 7.1 rodando em um iPhone 5, mas não consigo encontrar uma maneira de fazê-lo funcionar corretamente usando iOS 8 em um iPhone 6.
Barry Beerman
2
O mesmo para mim com a final do
iOS8.1
4
Ainda presente no IOS 9
o reverendo
45

Eu estava lutando com esse problema por várias horas, li todos os tópicos relevantes e descobri que o erro foi causado porque, nas configurações de privacidade do meu dispositivo, o acesso da câmera ao meu aplicativo foi bloqueado !!! Nunca neguei o acesso à câmera e não sei como foi bloqueada, mas esse era o problema!

Pantelis Proios
fonte
4
não tenho certeza se realmente funcionou para você, mas não funcionou para mim. Só espero que @KevinH esteja correto.
precisa
4
Não, o acesso à câmera está ativado para esse aplicativo no meu caso. Mas eu acredito que isso pode ser causado ainda que indirectamente pelas configurações: as alterações nas configurações às vezes não têm efeito imediato, alguém em Cupertino deve ter otimizado uma chamada para algum lugar sincronizar
Anton Tropashko
Esta sugestão resolveu o problema para mim. Eu já havia tocado em "Não permitir" quando o seletor de câmera apareceu no meu aplicativo. Eu pensei que me perguntaria cada vez que acessasse a câmera, mas não o fez. Eu tive que ir para Configurações> Privacidade> Câmera e ativar o controle deslizante do meu aplicativo. Então funcionou corretamente. Parece sorta bobo por parte da Apple para não pedir a cada vez ...
John Contarino
exatamente, às vezes não podemos pensar em questões levantadas para esse tipo de erro. thx amigo muito útil
Mr.Javed Multani
A melhor opção é antes de usar a câmera para detectar se a capacidade está ativa e, se não estiver, alertar o usuário de que tirar fotos não estará disponível até que a câmera seja ativada nas configurações. No iOS 10, é possível enviar o usuário para as configurações específicas do aplicativo (era possível antes do iOS 8, mas não é possível no iOS 8 e 9, se bem me lembro).
Kindaian
33

Não tenho pontos de reputação suficientes para comentar a resposta de @ greg acima, por isso adicionarei minhas observações aqui. Eu tenho um projeto Swift para iPad e iPhone. Eu tenho um método dentro do meu controlador de exibição principal (bit relevante abaixo). Quando eu testo isso em um telefone, tudo funciona corretamente e nenhum aviso é gerado. Quando o executo em um iPad, tudo funciona corretamente, mas recebo o aviso de captura instantânea da exibição. O interessante, porém, é que, quando eu corro em um iPad sem usar o controlador popover, tudo funciona corretamente sem aviso. Infelizmente, a Apple exige que o seletor de imagens seja usado dentro de uma janela popover no iPad, se a câmera não estiver sendo usada.

    dispatch_async(dispatch_get_main_queue(), {
        let imagePicker: UIImagePickerController = UIImagePickerController();
        imagePicker.sourceType = UIImagePickerControllerSourceType.SavedPhotosAlbum;
        imagePicker.mediaTypes = [kUTTypeImage];
        imagePicker.allowsEditing = false;
        imagePicker.delegate = self;

        if(UIDevice.currentDevice().userInterfaceIdiom == .Pad){ // on a tablet, the image picker is supposed to be in a popover
            let popRect: CGRect = buttonRect;
            let popover: UIPopoverController = UIPopoverController(contentViewController: imagePicker);
            popover.presentPopoverFromRect(popRect, inView: self.view, permittedArrowDirections: UIPopoverArrowDirection.Up, animated: true);
        }else{
            self.presentViewController(imagePicker, animated: true, completion: nil);
        }
    });
dlw
fonte
Parece que esta é uma sugestão correta, porque estou recebendo essa mensagem de erro mesmo com o iOS 9.0.2. Tenho o aplicativo somente para iPhone e, quando o executo no iPad Mini, vejo essa mensagem ao apresentar o seletor de imagens. Por alguma razão, o iOS pensa que eu executo o aplicativo para iPad.
John Tracid
16

Eu me deparei com isso depois de chamar UIImagePickerController presentViewController: do retorno de chamada para um delegado UIAlertView. Resolvi o problema pressionando o presentViewController: cancele o rastreamento de execução atual usando dispatch_async.

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    dispatch_async(dispatch_get_main_queue(), ^{
        UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
        imagePickerController.delegate = self;

        if (buttonIndex == 1)
            imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        else
            imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;

        [self presentViewController: imagePickerController
                           animated: YES
                         completion: nil];
    });
}
greg
fonte
Foi isso que resolveu para mim. Eu estava tentando apresentar o UIImagePickerController de dentro do bloco de ação de um UIAlertAction.
Jsefdlange #
o alertView foi descontinuado, isso funcionaria se eu usasse o assíncrono dentro de uma ação UIAlertViewController?
DrPatience
@DrPatience Claro. dispatch_async funciona em qualquer lugar que você quiser. Não sei se é necessário (depende do seu código). Leia sobre o GCD - ele tem muitos usos.
greg
12

Eu tive esse problema ao animar algumas visualizações e o aplicativo entra no modo de segundo plano e volta. Eu lidei com isso definindo uma bandeira como Ativa. Coloquei-o como NÃO em

- (void)applicationWillResignActive:(UIApplication *)application

e SIM em

- (void)applicationDidBecomeActive:(UIApplication *)application

e animar ou não animar meus pontos de vista de acordo. Cuidou do problema.

byedissident
fonte
11

Eu tive isso com um UIAlertControllerStyleActionSheet, dando ao usuário a opção de tirar uma foto com a câmera ou usar uma da biblioteca.

Eu tentei um ponto de interrupção simbólico na mensagem de erro insira a descrição da imagem aqui

Isso me mostrou que o erro é produzido pelo uso interno de um UICollectionView durante a apresentação

[self presentViewController:alert animated:YES completion:nil];

insira a descrição da imagem aqui

Corrigi isso definindo explicitamente o quadro antes de apresentar

[alert setPreferredContentSize: alert.view.frame.size];

Aqui está o método completo que está funcionando sem o erro

-(void)showImageSourceAlertFromSender:(id)sender{
UIButton *senderButton = (UIButton*)sender;
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *cameraAction = [UIAlertAction actionWithTitle:@"Camera" style:UIAlertActionStyleDefault
                                                     handler:^(UIAlertAction *action) {
                                                         [self takePhoto];
                                                     }];
UIAlertAction *libraryAction = [UIAlertAction actionWithTitle:@"Library" style:UIAlertActionStyleDefault
                                                      handler:^(UIAlertAction *action) {
                                                          [self selectPhotoFromLibraryFromSender:sender];
                                                      }];
[alert addAction:cameraAction];
[alert addAction:libraryAction];
alert.popoverPresentationController.delegate = self;
alert.popoverPresentationController.sourceRect = senderButton.frame;
alert.popoverPresentationController.sourceView = self.view;

[alert setPreferredContentSize: alert.view.frame.size];

[self presentViewController:alert animated:YES completion:^(){
}];}
Yedy
fonte
10

Você pode silenciar o aviso "Snapshotting a view" referenciando a viewpropriedade antes de apresentar o controlador de exibição. Fazer isso faz com que a exibição seja carregada e permite que o iOS a renderize antes de tirar a captura instantânea.

UIAlertController *controller = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
controller.modalPresentationStyle = UIModalPresentationPopover;
controller.popoverPresentationController.barButtonItem = (UIBarButtonItem *)sender;

... setup the UIAlertController ... 

[controller view]; // <--- Add to silence the warning.

[self presentViewController:controller animated:YES completion:nil];
Steve Shepard
fonte
Essa é uma dica quase incrivelmente útil. Obrigado!!!! (No meu caso, eu ainda obter o aviso, mas o app não falha.)
Fattie
No entanto, quando adiciono um cameraOverlayView, infelizmente ainda sinto esse problema, mesmo quando aplico esta dica.
Fattie
8

Para quem vê um problema com uma visualização em preto após a captura de imagem, ocultar a barra de status após a exibição do UIPickerController parece corrigir o problema.

UIImagePickerControllerSourceType source = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] ? UIImagePickerControllerSourceTypeCamera : UIImagePickerControllerSourceTypeSavedPhotosAlbum;
UIImagePickerController *cameraController = [[UIImagePickerController alloc] init];
        cameraController.delegate = self;
        cameraController.sourceType = source;
        cameraController.allowsEditing = YES;
        [self presentViewController:cameraController animated:YES completion:^{
            //iOS 8 bug.  the status bar will sometimes not be hidden after the camera is displayed, which causes the preview after an image is captured to be black
            if (source == UIImagePickerControllerSourceTypeCamera) {
                [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
            }
        }];
Dan
fonte
1
! totalmente salvou meu dia eu tentei métodos acima, nenhum worked.and isso funcionou
Stan
Solução não está funcionando. Acho que quando capturamos uma imagem naquele momento, a StatusBar já está oculta.
Mihir Oza
5

Encontrei o mesmo problema e tentei de tudo. Eu tenho dois aplicativos diferentes, um no objetivo-C e outro no rápido - ambos têm o mesmo problema. A mensagem de erro aparece no depurador e a tela fica preta após a primeira foto. Isso acontece apenas no iOS> = 8.0, obviamente é um bug.

Eu encontrei uma solução difícil. Desligue os controles da câmera com imagePicker.showsCameraControls = false e crie seu próprio overlayView com os botões ausentes. Existem vários tutoriais sobre como fazer isso. A estranha mensagem de erro permanece, mas pelo menos a tela não fica preta e você tem um aplicativo em funcionamento.

Thomas Zimmer
fonte
Eu tive exatamente o mesmo problema que você, veja minha resposta abaixo.
Dan
5

Isso pode ser um erro do ImagePickerController interno. Meu código está funcionando, mas ocasionalmente trava no iPhone 6 Plus.

Eu tentei todas as soluções sugeridas por outras respostas, mas não houve sorte. Problema finalmente resolvido após a mudança para JPSImagePickerController .

JonSlowCN
fonte
3

Eu tentei de tudo, meu problema era que o seletor de imagens para a câmera e a biblioteca de fotos desapareceu logo após a exibição. Eu o resolvi com a seguinte linha (rápida)

imagePicker.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
Waffeln
fonte
3

Tenho certeza de que isso é apenas um bug no iOS 8.0. É reproduzível com os aplicativos POC mais simples que não fazem nada além de tentar apresentar um UIImagePickerController como você está fazendo acima. Além disso, não há um padrão alternativo para exibir o seletor de imagens / câmera, que eu saiba. Você pode até baixar o aplicativo de exemplo Using UIImagePickerController da Apple, executá-lo e ele gerará o mesmo erro imediatamente.

Dito isto, a funcionalidade ainda funciona para mim. Além do aviso / erro, você tem problemas com o funcionamento do seu aplicativo?

Gaurav Patel
fonte
3

Se estivermos usando o UIImagePickerController propriedade como, esse aviso desaparecerá.suponha que não estamos usando o resultado de UIImagePickerController, se estamos instanciando o UIImagePickerControllerdentro de uma função.

Antony Ouseph
fonte
2

Chamar esse método funcionou para mim. Coloque-o depois de apresentar sua exibição.

[yourViewBeingPresented.view layoutIfNeeded];
Bobby
fonte
1

Também encontrei o mesmo problema e resolvi-o verificando se a câmera está disponível:

BOOL cameraAvailableFlag = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
    if (cameraAvailableFlag)
        [self performSelector:@selector(showcamera) withObject:nil afterDelay:0.3];
aftab muhammed khan
fonte
1
isSourceTypeAvailable retorna true mesmo que eu tenha negado o acesso à câmera do meu aplicativo. O visor fica em branco se o acesso à câmera for negado.
21415
1

Me deparei com este problema. Quando ligamos para a câmera e liberamos as visualizações produzidas esse problema. Por exemplo, chame uma câmera e defina view nil no método viewDidDisappear, esse erro ocorrerá, pois não há retorno de chamada para o evento da câmera. Verifique também este caso para esse erro.

Gobi M
fonte
1

Eu recebi o mesmo bug, recebendo a mensagem abaixo no console enquanto abria a câmera.

A captura instantânea de uma exibição que não foi renderizada resulta em uma captura instantânea vazia. Certifique-se de que sua exibição tenha sido renderizada pelo menos uma vez antes de fazer o snapshot ou após as atualizações da tela. '

Para mim, o problema estava com o nome de exibição do pacote no arquivo Info.plist. Estava vazio de alguma forma, coloquei o nome do meu aplicativo lá e agora está funcionando bem. Não recebi nenhum alerta de permissão da câmera por causa do nome de exibição do pacote vazio.it impediu a exibição da renderização.

o problema não estava no modo de exibição, mas apresentando-o sem uma permissão. você pode verificá-lo nas configurações -> privacidade -> câmera, se o aplicativo não estiver listado, o problema pode ser o mesmo.

Shabeer Ali
fonte
1

Estou usando o Phonegap, mas esse tópico continua sendo o primeiro ao pesquisar a mensagem de erro no Google.

Para mim, esse problema desapareceu ao definir o tipo de imagem para PNG.

encodingType : Camera.EncodingType.PNG

Portanto, toda a linha é:

 navigator.camera.getPicture(successFunction, failFunction, { encodingType : Camera.EncodingType.PNG, correctOrientation:true, sourceType : Camera.PictureSourceType    .PHOTOLIBRARY, quality: 70, allowEdit : false , destinationType: Camera.DestinationType.DATA_URL});

Sua milhagem pode variar, mas esse foi o truque para mim.

Jannunen
fonte
1

Como alternativa, considere usar drawViewHierarchyInRect:

Rápido:

extension UIImage{

    class func renderUIViewToImage(viewToBeRendered: UIView) -> UIImage
    {
        UIGraphicsBeginImageContextWithOptions(viewToBeRendered.bounds.size, true, 0.0)
        viewToBeRendered.drawViewHierarchyInRect(viewToBeRendered.bounds, afterScreenUpdates: true)
        viewToBeRendered.layer.renderInContext(UIGraphicsGetCurrentContext()!)

        let finalImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return finalImage
    }
}

Objetivo-C:

- (UIImage *)snapshot:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, 0);
    [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

Veja também:

Eric
fonte
0

No meu caso (XCode 7 e iOS 9), eu uso UINavigationController"oculto", então tenho que adicionar UINavigationControllerDelegateà câmera ou rolo presente e funcionar como deveria! And pickerControllerDelegate.selftambém não exibe erro!

Daniel Arantes Loverde
fonte