@IBDesignable error: IB Designables: falha ao atualizar o status do layout automático: o Interface Builder Cocoa Touch Tool travou

157

Eu tenho uma subclasse muito simples de UITextView que adiciona a funcionalidade "Espaço reservado" que você pode encontrar nativa para o objeto Campo de texto. Aqui está o meu código para a subclasse:

import UIKit
import Foundation

@IBDesignable class PlaceholderTextView: UITextView, UITextViewDelegate
{
    @IBInspectable var placeholder: String = "" {
        didSet {
            setPlaceholderText()
        }
    }
    private let placeholderColor: UIColor = UIColor.lightGrayColor()        
    private var textColorCache: UIColor!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.delegate = self
    }
    
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.delegate = self
    }
    
    func textViewDidBeginEditing(textView: UITextView) {
        if textView.text == placeholder {
            textView.text = ""
            textView.textColor = textColorCache
        }
    }
    
    func textViewDidEndEditing(textView: UITextView) {
        if textView.text == "" && placeholder != "" {
            setPlaceholderText()
        }
    }
    
    func setPlaceholderText() {
        if placeholder != "" {
            if textColorCache == nil { textColorCache = self.textColor }
            self.textColor = placeholderColor
            self.text = placeholder
        }
    }
}

Depois de alterar a classe do UITextViewobjeto no Identity Inspector para PlaceholderTextView, eu posso definir a Placeholderpropriedade muito bem no Attribute Inspector. O código funciona muito bem ao executar o aplicativo, mas não exibe o texto do espaço reservado no criador da interface. Também recebo os seguintes erros sem bloqueio (presumo que seja por isso que não seja renderizado em tempo de design):

erro: IB Designáveis: falha ao atualizar o status do layout automático: o Interface Builder Cocoa Touch Tool travou

erro: IB Designáveis: falha ao renderizar a instância do PlaceholderTextView: A renderização da exibição levou mais de 200 ms. Seu código de desenho pode sofrer com desempenho lento.

Não consigo descobrir o que está causando esses erros. O segundo erro não faz nenhum sentido, pois nem estou substituindo drawRect (). Alguma ideia?

Albert Bori
fonte
1
Eu estava recebendo esse erro. O objeto funcionou bem em um projeto de teste, mas não no meu projeto principal (em uma tabela). De acordo com developer.apple.com/library/mac/recipes/… , eu escolhi Choose Editor> Debug Selected Views. Em seguida, obtive "Não foi possível depurar visualizações" "Verifique se sua estrutura possui as configurações de compilação corretas para a criação para iOS". Nada apareceu no Google por esse erro.
Matt

Respostas:

238

Há relatórios de falha gerados quando o Interface Builder Cocoa Touch Tool falha. Teses estão localizadas ~/Library/Logs/DiagnosticReportse nomeadas IBDesignablesAgentCocoaTouch_*.crash. No meu caso, eles continham um rastreamento de pilha útil que identificou o problema no meu código.

Petter
fonte
1
Obrigado! Isso foi super útil! Onde você encontrou as informações sobre os relatórios de falhas? :)
Ben-G
57
No meu caso, descobri que initFrame(frame: CGRect)deve ser definido. Faça isso se você fornecer seu próprio initmétodo (s).
Travis
Essa foi a melhor solução. Eu não estava implementando initWithFrame em uma das visualizações.
HotFudgeSunday
3
Usei os relatórios de diagnóstico e, como o @Travis mencionou, precisava substituir init(frame: CGRect)explicitamente o porque tinha um inimétodo personalizado . Você pode procurar use of unimplemented initializer 'init(frame:)'diretamente no relatório de falha Application Specific Informationno relatório. Obrigado rapazes! Dupla vitória nesta resposta!
26416 Chris
4
Como sempre, esse arquivo de log também está disponível no aplicativo console macOS, no grupo Relatórios de diagnóstico do usuário .
Paulo Mattos
51

Eu tive o mesmo problema algumas vezes. As duas vezes começaram quando eu carregava uma ponta do IBDesignable no storyboard quando a ponta não era capaz de caber na vista (ou seja, eu tinha um botão fora do UIView, mas ainda estava na ponta). Depois que eu consertei o Xcode, ele ainda me dava erros, então reiniciei o Xcode até que ele parasse aleatoriamente de me dar o erro.

Eu espero que isso ajude.

ATUALIZAÇÃO: Acabei de matar todos os processos chamados "Interface Builder Cocoa Touch Tool", reiniciei o Xcode e o erro desapareceu. Não sei se isso sempre funcionará ou não.

Dustin Williams
fonte
2
Embora eu ainda não entenda o motivo, se você não substituir nenhum dos initmétodos, o código publicado como parte da pergunta não mostrará mais os IB Designableserros e o espaço reservado será renderizado corretamente no Interface Builder.
Willington Vega
2
Talvez isso seja um bug e só precisamos esperar que seja corrigido. Talvez no Xcode 6.3.
Youssef Moawad
3
XCode 7.1.1 e ainda presente. Reiniciar o XCode não resolveu o problema. Eu tive que matar manualmente todos os processos chamados Interface Builder Cocoa Touch Tool, o XCode travou, reiniciou e começou a funcionar.
Cristian Pena
1
Ponto importante: Na verdade PRIMEIRO matar o Interface Builder processos, em seguida, parar XCode - se você fazê-lo de outra maneira em torno dos persiste problema ...
theeye
2
XCode 8.1 esse erro ainda ocorre. Originalmente causado por não ter a substituição do init, mas persistiu após a adição do init. Tinha que matar processos Interface Builder como descrito xcode reinicie como diz @TheEye
John Fowler
39

No meu caso, eu estava fazendo o próximo nos métodos initWithFrame / initWithCoder para criar a exibição:

className = NSStringFromClass([self class]);
self.view = [[[NSBundle mainBundle] loadNibNamed:className owner:self options:nil] firstObject];

Parece que eu não deveria usar o pacote principal , mas o pacote da classe. Então, substituí esse código pelo seguinte e funcionou:

bundle = [NSBundle bundleForClass:[self class]];
className = NSStringFromClass([self class]);
self.view = [[bundle loadNibNamed:className owner:self options:nil] firstObject];

Eu pensei que talvez isso possa ajudar alguém.

jmoukel
fonte
1
Isso também corrigiu meu problema! Obrigado @jmoukel!
precisa saber é o seguinte
Aquele corrigiu meu problema. Homem!!! Eu não conseguia notar a linha "bundleForClass", mesmo tendo analisado essa solução algumas vezes. :(
elk_cloner
let bundle = Bundle(for: ValidatingTextField.self)em Swift
Cfr
14

Você poderia selecionar sua exibição personalizada no Interface Builder e uso, em seguida Editor, Debug Selected Views. Ele iniciará a chamada IBDesignableAgentCocoaTouchsessão de depuração quando todos os pontos de interrupção (incluindo pontos de interrupção de exceção) funcionarem e você puder identificar exatamente o local em que sua exibição falha.

Fyodor Volchyok
fonte
Perfeito! Isso também encontrou meu problema - uma fonte incorreta. O que explica por que apenas um dos seis IBDesignables muito semelhantes estava falhando.
Zkarj
13

Para o Xcode 8 - Swift

Adicionar valor opcional como valor padrão ao @IBInspectablecausar problema para mim.

Isso não vai funcionar:

@IBInspectable var repeatImage: UIImage = UIImage(named:"myImage")!{
      didSet {
       // configureView
      }
}

Isso deve funcionar:

@IBInspectable var repeatImage: UIImage = RepeatImageView.getDefaultImage() {
    didSet {
        // configureView()
    }
}

class func getDefaultImage() -> UIImage {
    if let defaultImage = UIImage(named: "myImage") {
        return defaultImage
    } else {
        return UIImage()
    }
}
Mohammad Zaid Pathan
fonte
@DungTran Qual é o seu problema?
Mohammad Zaid Pathan
1
O manuseio opcional evita a falha. Mas você sabe o que está fazendo com que UIImage (nomeado :) retorne nulo de forma consistente?
ScottyBlades
Comentando este código fixo para mim `@objc @available (*, obsoleto, renomeado: "backgroundColor") @IBInspectable var pública signatureBackgroundColor: UIColor = .white {didSet {backgroundColor = signatureBackgroundColor}}`
PhoneyDeveloper
9

Eu estava tendo problemas semelhantes com o Interface Builder que renderizavam designáveis.

Usando a técnica sugerida nesta resposta , consegui rastrear o problema para o uso de literais de imagem.

Falha na renderização

self.backgroundImage.image =  #imageLiteral(resourceName: "rectangleCenter")

Nenhuma falha de renderização

self.backgroundImage.image =  UIImage(named: "rectangleCenter")
Nick Cross
fonte
Você é um herói.
Nathanitter 29/08
Alguma idéia de por que literais de imagem são incompatíveis com o IB? Eu tive o mesmo problema.
SwiftsNamesake
6

Na verdade, se você tiver alguns atributos antigos definidos pelo usuário (que não são válidos para a exibição atual) em qualquer exibição do storyboard, isso pode causar uma falha no seu agente.

Além disso, às vezes acontece apenas por causa de um bug desagradável do Xcode. Para conferir, quando estiver no storyboard, desmarque Editor> Atualizar automaticamente vistas, depois vá para outro arquivo, limpe e reinicie seu projeto. Depois de inserir o storyboard novamente, você pode clicar em Editor> Atualizar Visualizações e verificar o automático novamente. Essa também resolveu o meu problema uma vez.

Se os dois não funcionaram, provavelmente você fez algo errado na sua visualização do IBDesignable. Escolha suas visualizações com falha no storyboard e depure clicando em Editor> Visualizações de Depuração

Yusuf Kamil AK
fonte
Você é um presente de Deus.
andrewcar
4

Este não é o caso desta pergunta, mas talvez eu ajude outra pessoa.

Eu tive um problema semelhante quando na minha classe @IBDesignable não implementei os dois:

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    // custom setup
}

override init(frame: CGRect) {
    super.init(frame: frame)

    // custom setup
}
tzaloga
fonte
Você sempre deve implementar os dois métodos init. Init with frame é usado quando você inicia sua visualização a partir do código e init com umDecoder é usado no InterfaceBuilder.
Skodik.o
4

Eu tive o mesmo problema e o resolvi adicionando o 'use_frameworks!' ao Podfile do meu projeto.

Espero que ajude você.

Jimmy Ng
fonte
Isso funcionou para mim quando eu tive esse problema com JVFloatLabeledTextField
saswanb
Foi isso que funcionou para mim, adotando um projeto Obj-C mais antigo que estava bastante desatualizado. O IB acende como uma árvore de Natal depois disso! Obrigado.
chamou ..
3

No meu caso, estava de alguma forma relacionado a uma estrutura de cartago que eu estava usando. Eu tive que adicionar $ (PROJECT_DIR) / Carthage / Build / iOS aos caminhos de pesquisa do caminho de execução configuração de compilação dos

AkademiksQc
fonte
Depois de tentar todas as outras soluções postadas ... essa foi a única correção que funcionou para mim! Obrigado!
Joel
3

No meu caso, houve um problema com o OneSignal. Aparentemente, eles têm um bug na versão 2.2.0 e acima. Mudou para 2.1.6 e tudo está ótimo de novo!

Confira isso .

Paul Razvan Berg
fonte
1

Quando eu depurei isso, descobri que existem algumas classes que estão modificando a interface do usuário. Normalmente, marquelabel, que é uma subclasse de UILabel ou qualquer outra classe de subclasse de UIView, desenhando a interface do usuário em tempo de execução e colidindo com o mecanismo de Autolayout. Tente dar largura ou altura fixas para essas visualizações personalizadas. Se isso não resolver o seu problema, tente as seguintes soluções: -

Solução 1: - Remova o comentário #use_frameworks dentro do seu arquivo pod.

Solução 2: - Tente excluir os dados derivados. 1. Feche a janela Editor do seu Xcode e saia do simulador -> 2. Vá para Xcode Preferences -> Locations -> 3. Clique na pequena seta cinza mostrando o caminho dos dados derivados -> 4. Selecione seu projeto -> 5. Exclua todas as pastas dentro -> 6. Saia do Xcode e reabra

Ashish Pisey
fonte
1

Adicione-o ao final do seu Podfile e execute pod install

# Workaround for Cocoapods issue #7606

    post_install do |installer|
        installer.pods_project.build_configurations.each do |config|
            config.build_settings.delete('CODE_SIGNING_ALLOWED')
            config.build_settings.delete('CODE_SIGNING_REQUIRED')
        end
    end
Tissa
fonte
1

Adicione este script no final do meu Podfilee executei pod installnovamente.

post_install do |installer|
    installer.pods_project.build_configurations.each do |config|
        config.build_settings.delete('CODE_SIGNING_ALLOWED')
        config.build_settings.delete('CODE_SIGNING_REQUIRED')
    end
end
Haroldo Gondim
fonte
1

Um dos principais problemas é quando você cria o @ IBDesignable, verifique se o arquivo cocoapod não está incluído nos UITests, caso contrário, causará essa falha.

Modesto Cabrera
fonte
0

Acho que o motivo é o seu xib não ter o mesmo tamanho do design do storyboard. Verifique se o xib tem a mesma altura e largura.

user6476366
fonte
0

Eu estava apenas faltando esta linha de código platform :ios, '7.0' e o problema foi resolvido. Apenas esta linha no seu arquivo pod e a atualização do problema do seu pod serão resolvidas.

Shahzaib Maqbool
fonte
0

Para mim, faltava um certificado de assinatura, porque nunca executei o aplicativo, portanto o Xcode ainda não criou um certificado. Depois de executar o aplicativo, a IBDesignablerenderização funcionou bem.

Florian Pfisterer
fonte
0

É como se você obtivesse o código de outro desenvolvedor e recebesse esse erro. Apenas corra

pod install

Isso funcionou para mim. Espero que ajude.

Dhruv Khatri
fonte
0

Verifique se você não está inicializando diretamente UIImageouUIFont usando recursos ou fontes adicionados ao seu projeto.

Eu sempre crio um private func setUp()em minhas classes @IBDesignablepersonalizadas UI. que é chamado de init(frame: CGRect), init?(coder aDecoder: NSCoder). Então, finalmente atualizei setup()o seguinte.

private func setUp() {

     //... Doing initial configurations

     // iconImageView.image = UIImage(named: "IconImageName")! // Causing the Crash, use if let OR guard let instead
     if let icon = UIImage(named: "IconImageName") {
          iconImageView.image = icon
          iconImageView.frame.size = icon.size
     }

     // nameLabel.font =  UIFont(name: "Calibri-Light", size: 15.0) // Causing the Crash, use if let OR guard let instead
     if let font = UIFont(name: "Calibri-Light", size: size) {
          nameLabel.font =  font
     } else {
          nameLabel.font = UIFont.systemFont(ofSize: size) 
     }

     // Doing other stuffs
}
Sauvik Dolui
fonte
-1

Deixe-o construir e executar no simulador se você tiver algum erro em algum outro lugar no projeto. Basta comentar e executar o design primeiro para atualizar o design e descomentar os outros códigos. Funciona para mim.

Daniel
fonte