IB_DESIGNABLE, IBInspectable - Construtor de interface não atualiza

91

Eu tenho o seguinte conjunto de códigos:

CustomView.h

#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface CustomView : UIView

@property (nonatomic) IBInspectable UIColor *borderColor;
@property (nonatomic) IBInspectable CGFloat borderWidth;
@property (nonatomic) IBInspectable CGFloat cornerRadius;

@end

CustomView.m

#import "CustomView.h"

@implementation CustomView

- (void)setBorderColor:(UIColor *)borderColor {
    _borderColor = borderColor;
    self.layer.borderColor = borderColor.CGColor;
}

- (void)setBorderWidth:(CGFloat)borderWidth {
    _borderWidth = borderWidth;
    self.layer.borderWidth = borderWidth;
}

- (void)setCornerRadius:(CGFloat)cornerRadius {
    _cornerRadius = cornerRadius;
    self.layer.cornerRadius = cornerRadius;
}

@end

(Para referência do Swift, esse problema também estava ocorrendo com o código Swift)

CustomView.swift

@IBDesignable
class CustomView : UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
    }

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

    @IBInspectable var borderColor : UIColor = UIColor.clearColor() {
        didSet {
            self.layer.borderColor = borderColor.CGColor
        }
    }

    @IBInspectable var borderWidth : CGFloat = 0.0 {
        didSet {
            self.layer.borderWidth = borderWidth
        }
    }

    @IBInspectable var cornerRadius : CGFloat = 0.0 {
        didSet {
            self.layer.cornerRadius = cornerRadius
        }
    }
}

Eu adicionei um UIViewa um controlador de visualização no storyboard e defini sua subclasse como CustomView.

insira a descrição da imagem aqui

Isso adiciona a linha "Designables". Ele está preso em "Atualizando" e a dica de ferramenta diz "Aguardando a criação do destino". Nunca muda deste status.

Quando passo para a inspeção de atributos, posso definir estas IBInspectablepropriedades:

insira a descrição da imagem aqui

E uma vez definidos, eles também aparecem nos "Atributos de tempo de execução definidos pelo usuário":

insira a descrição da imagem aqui

No entanto, o status "Designáveis" nunca vai além de "Atualizando" com a mesma dica de ferramenta (tentei construir Cmd + B várias vezes, nada muda).

Além disso, conforme defino as IBInspectablepropriedades, recebo um aviso para cada uma:

IBDesignables - Ignorando o atributo de tempo de execução definido pelo usuário para o caminho da chave "borderColor" na instância de "UIView" ... esta classe não é compatível com a codificação do valor da chave para a chave borderColor.

Captura de tela dos avisos gerados:

insira a descrição da imagem aqui


Estou familiarizado com os problemas de conformidade da codificação de valores-chave e geralmente sei como resolvê-los ... mas não entendo como resolver esse problema aqui. De acordo com o inspetor de identidade da visualização, a visualização é um "CustomView" (não um "UIView" normal, que não tem essas propriedades). E se a visualização não fosse uma "CustomView", essas propriedades projetáveis ​​não apareceriam no Attributes Inspector, certo? Mas quando o Interface Builder tenta aplicar esses atributos à visão, ele volta a pensar que a classe da visão é "UIView" e não pode aplicar os atributos.

Qualquer ajuda? Por favor, deixe-me saber se eu esqueci algum detalhe importante, mas para valer a pena, eu segui este tutorial exatamente (diferente de ObjC vs Swift). Também é importante notar que segui este tutorial exatamente em outra máquina e funcionou perfeitamente (eu pretendia fazer este post ontem à noite, mas o computador que eu estava usando não tinha esse problema).


Com base em comentários, foi sugerido que talvez o .marquivo não esteja incluído e isso possa estar causando o problema. Achei que certamente teria saído do meu caminho para que esse cenário fosse o caso, mas verifiquei mesmo assim.

insira a descrição da imagem aqui

Quando comecei a tentar fazer isso, eu estava entendendo que as IB_DESIGNABLEaulas deveriam fazer parte de uma UIKitestrutura diferente . Portanto, nesta primeira captura de tela, você pode ver que configurei uma estrutura "CustomViews", que tem uma classe CustomView,. Você também verá aqui que eu também criei um OtherView, que é idêntico a CustomView, exceto que não está em uma estrutura separada. O problema idêntico persiste no storyboard entre as duas classes, no entanto.

Aqui temos uma captura de tela indicando que CustomView.mestá incluído para ser construído com a CustomViewsestrutura:

insira a descrição da imagem aqui

Enquanto isso, a captura de tela a seguir indica várias coisas:

  • CustomViews.framework está adequadamente incluído no projeto principal.
  • OtherView.mtambém é incluído como uma fonte de compilação, portanto, mesmo que haja algo errado com CustomView, OtherViewdeve funcionar, porém gera erros idênticos.
  • Main.storyboarde LaunchScreen.xibestão aparecendo em vermelho. Não tenho ideia do porquê, e não tenho a menor idéia de por que LaunchScreen.xibdeveria (eu não toquei neste arquivo), embora eu possa dizer depois de olhar para outros projetos, Main.storyboardtambém aparece em vermelho para esses projetos, e eu estou não fazendo nada com IB_DESIGNABLEou IBInspectablelá.

insira a descrição da imagem aqui


Eu tentei e tentei novamente várias vezes. Funciona sempre no meu computador em casa - não consigo reproduzir o problema descrito nesta pergunta em casa. No trabalho, nunca funciona. O problema descrito nesta pergunta acontece sempre.

Ambos os computadores são Mac Minis adquiridos novos este ano (não os novos modelos, modelo do final de 2012). Ambos os computadores estão executando o OS X Yosemite 10.10. Ambos os computadores estão executando o Xcode versão 6.1. Em casa, a configuração é (6A1052d). Esta manhã, posso confirmar que ambos os computadores estão executando compilações idênticas do Xcode.

Outros me sugeriram que pode ser RAM ruim. Isso parece rebuscado para mim. Reiniciei o projeto várias vezes, reiniciei o computador várias vezes. Parece-me que se houvesse uma RAM danificada em um computador com aproximadamente 6 meses de idade, eu estaria vendo outros problemas e que esse problema seria menos consistente. Mas esse exato problema persiste apesar de várias vezes reiniciar todo o projeto do zero e reiniciar totalmente no computador.


Deve ser importante observar que, se eu realmente compilar e executar este projeto, a visualização personalizada com as IBInspectablepropriedades realmente será exibida como espero que o storyboard a exiba. Imagino que esse seria o caso mesmo sem as diretivas IB_DESIGNABLEe IBInspectable, no entanto, já que elas são criadas como Atributos de tempo de execução definidos pelo usuário.

nhgrif
fonte
Bem, foi apenas uma ideia. Removi CustomView.m do destino e recebi avisos semelhantes ao executar o aplicativo.
Martin R
Isso parece um verdadeiro gremlin, dada a sua comparação com uma máquina aparentemente idêntica (que difere de alguma forma). Você já tentou postar em devforums? Parece que você está voando às cegas sem informações adicionais e seu processo parece razoável e racional. O aviso "build" pode não significar muito, pois o Xcode está repleto de mensagens de erro enganosas. Para começar, você tentou Editor -> "debug selected view", certo? (Provavelmente não funcionará, mas vale a pena verificar). Além disso, alguma coisa aparece no aplicativo de console (registro)?
Chris Conover
Estou tendo o mesmo problema. Minas com um único arquivo xib contendo um IB_DESIGNABLE. No entanto, verificando minha configuração, já ativei a atualização automática e agora tentei as atualizações manuais, limpando primeiro os dados derivados, etc. Até agora, nada funcionou. O estranho é que eu tinha esse controle funcionando bem, depois parou. E eu não acho que mudei nenhum código entre eles. Louco.
drekka
Estava mostrando avisos conforme acima. Agora criei uma segunda classe com o código copiado do design IB original. Esta classe funciona perfeitamente e quando voltei para a classe não trabalhadora original, agora funciona bem. A partir disso, concluí que há algum cache em algum lugar (não em dados derivados) que não é limpo até que o design ib original seja trocado por outro design ib. Mudar para um UIView não parece limpar esse cache. Apenas outro ib projetável. Vai entender :-)
drekka

Respostas:

75

Com base na sugestão do chrisco de depurar a visão selecionada (o que eu já tinha feito, mas tentei novamente para uma boa medida), notei algumas outras opções na parte inferior do menu Editor.

  • Atualizar visualizações automaticamente
  • Atualizar todas as visualizações

Cliquei em "Atualizar todas as visualizações" e depois que o Xcode pensou um pouco, de repente o storyboard estava exibindo minha visualização conforme o esperado (aplicando corretamente minhas IBInspectablepropriedades).

insira a descrição da imagem aqui

Em seguida, repassei todo o processo para confirmar que essa é a solução.

Criei uma nova classe ThirdView,. Esta classe é idêntica às outras, novamente. Mudei a classe da minha visão para ThirdViewe peguei algo um pouco diferente desta vez:

insira a descrição da imagem aqui

Clicar em "Mostrar" para os avisos:

insira a descrição da imagem aqui

Um novo desta vez:

Usando a classe UIView para objeto com classe personalizada porque a classe ThirdView não existe.

Isso não é realmente mais útil do que o que já existia. Além disso, agora os outros três avisos dobraram para 6 estranhamente.

De qualquer forma, se eu clicar em "Atualizar todas as visualizações" no menu suspenso do Editor novamente, todos os erros desaparecerão e, mais uma vez, a visualização será exibida corretamente.

Ainda assim, até este ponto, tudo o que eu fiz foi coisas que nunca mexi em casa. Em casa, simplesmente funcionou. Então, ativei "Atualizar automaticamente as visualizações" e criei um "FourthView" para testar - mais uma vez, idêntico aos três primeiros.

Depois de alterar a classe da visualização para "FourthView", o rótulo designável disse "Atualizando" por um breve momento e finalmente disse "Atualizado":

insira a descrição da imagem aqui

Então, eu verifiquei meu computador em casa. A opção "Atualizar visualizações automaticamente" está ativada no computador que estava sempre funcionando. Estava desligado no computador que não estava. Não me lembro de ter tocado nessa opção do menu. Eu não posso nem dizer com certeza se ele existia antes do Xcode 6. Mas essa opção é o que estava fazendo a diferença.


TL; DR, se você estiver tendo o mesmo problema descrito na pergunta, certifique-se de que "Atualizar automaticamente as visualizações" esteja ativado (ou manualmente "Atualizar todas as visualizações" quando precisar de uma atualização no IB):

insira a descrição da imagem aqui

nhgrif
fonte
2
Na verdade, eu estava procurando como desativá-lo, pois ele continua renderizando em segundo plano, tornando os MacBooks mais antigos muito lentos. Obrigado!
Departamento B de
Isso pode resolver temporariamente, mas verifique a resposta de @ Martin-Gilles Lavoie
Ashley Mills
22

Eu tenho mais alguns detalhes que podem fazer com que suas classes IBDesignable não sejam carregadas.

Selecione seu storyboard / xib problemático onde suas visualizações personalizadas devem ser exibidas.

Na área do navegador, vá para o Report Navigator em sua área de trabalho / projeto XCode.

No menu Editor do XCode, clique (conforme mencionado por nhgrif), a opção "Atualizar todas as visualizações". Isso fará com que o IB lance uma compilação para um monte de coisas que você, tenho certeza, não esperaria.

No Report Navigator, clique em "By Group" para filtrar o conteúdo e veja a seção "Interface Builder". Você verá que, para carregar a estrutura de visualizações personalizadas do IBDesignable, ela compilará MUITAS coisas. Se algum desses alvos NÃO compilar, como alvos de teste de unidade (talvez obsoletos) (mesmo se eles não estiverem totalmente relacionados ao código que carrega essas visualizações ou storyboard), o IB falhará ao carregar sua dll.

No meu caso, o IB tentou compilar 8 alvos, incluindo 4 onde testes de unidade que não foram atualizados desde as recentes mudanças de refatoração nas quais estamos trabalhando.

A maioria das alterações / correções de código que fiz para que o IB carregue e exiba corretamente minhas visualizações personalizadas, quando não relacionadas ou mesmo vinculadas a essas classes, nem carregaria o storyboard durante a execução desses testes de unidade. Mesmo assim, o IB dependia de toda a compilação do espaço de trabalho para que funcionasse.

Martin-Gilles Lavoie
fonte
Ei, então como faço para impedir que o IB tente carregar e exibir visualizações não relacionadas ou vinculadas a essas classes?
HannahCarney
Presumo que tenha a ver com dependências de cabeçalho. Se as classes projetáveis ​​estiverem tocando em outras classes, no momento em que o cabeçalho for visto, ele construirá essas implementações relacionadas. A Apple está brincando com o código do gráfico de dependência de origem no XC7GM, que falha totalmente em nosso projeto, com o XCode travando durante a construção do gráfico. Os 7.1betas a seguir não apresentam o problema. Nosso sistema de compilação automatizado ainda depende do 6.4 no momento, então não investigamos como resolver isso com mais detalhes no XC6.4. Iremos pular direto para 7.1GM.
Martin-Gilles Lavoie
Se você tem vários destinos / projetos, esta é a resposta absolutamente certa e realmente corrige o problema - TODOS os destinos devem ser compilados de forma limpa, eu nem sabia que havia uma seção "Construtor de Interface" no navegador de relatórios! Todas as outras respostas que vi são basicamente acenos de mão que podem consertar temporariamente, mas esta é a solução definitiva. Bem feito.
Ashley Mills
3
Então, de acordo com isso, podemos concluir que o atributo IB_DESIGNABLE é uma merda e uma perda de tempo total. Apenas evite usá-lo.
m8labs de
IB_DESIGNABLE não tem nada a ver com o problema e a solução listados acima. É apenas um sinalizador NO-OP para o IB detectar coisas utilizáveis. Você só precisa manter uma casa limpa.
Martin-Gilles Lavoie
22

Apenas uma dica rápida para qualquer pessoa com esse problema: lembre-se de especificar o tipo da variável.

// Doesn't show up in IB
@IBInspectable var includeLeftSection = true

// Shows now that it knows the type
@IBInspectable var includeLeftSection : Bool = true
GoldenJoe
fonte
6

Recebi o mesmo aviso Ignoring user defined runtime attribute for key path .., embora tenha absoluta certeza de que não fiz nada de errado com minha classe de visualização IBDesignable personalizada.

Acontece que, no meu caso, tinha a ver com o cache do Xcode.

rm -rf ~/Library/Developer/Xcode/DerivedData/*

Limpe DerivedDatae o aviso desaparece.

Samwize
fonte
1
Atalho no XCode para obter o mesmo resultado: ⌘⇧K
Mojo66
@ Mojo66 Acredito que o Clean Build é diferente de limpar a pasta DerivedData. Claro, às vezes a compilação limpa é boa o suficiente para resolver certos problemas de cache do Xcode.
samwize
@ Mojo66 você provavelmente quis dizer ⌘⌥⇧K (cmd + alt + shift + K)
tzaloga
5

No caso de qualquer outra pessoa se deparar com o erro IB Designables class does not exist, pelo mesmo motivo que eu. A resposta principal não foi meu problema ... mas aqui está um problema ligeiramente relacionado ...

Há uma propriedade oculta no código-fonte do storyboard chamada customModule.

Por exemplo, eu tinha uma classe chamada ForwardArrow dentro de uma estrutura separada que acidentalmente adicionei ao meu destino principal.

Portanto, o XML para algumas visualizações acabou como customClass = "ForwardArrow" customModule = "MainTargetNameWasHere"

Quando eu os removi do alvo principal na construção, o storyboard não atualizou MainTargetNameWasHere para CustomViews que é o framework onde ele estava localizado e começou a dar aquele erro de nenhuma classe encontrada.

Portanto, TLDR; Certifique-se de que, se o seu IBDesignable estiver em outra estrutura, o atributo customModule xml em seu storyboard esteja definido com o valor correto. E se não estiver lá, adicione-o.

Exemplo da minha fonte:

<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MUG-jc-2Ml" customClass="ForwardArrow" customModule="CustomViews">
Dave Thomas
fonte
1
Puta merda, isso tem me deixado louco por um dia. Que inseto desagradável.
GoldenJoe
5

Como meu exemplo, eu estava usando o CheckboxButton via pod e os gráficos do checkbox nunca aparecem no storyboard, embora eu tenha os mesmos problemas descritos na pergunta aqui:

aviso: IB Designables: Usando a classe UIView para objeto com classe personalizada porque a classe CheckboxButton não existe

e

aviso: IB Designables: Ignorando o atributo de tempo de execução definido pelo usuário para o caminho da chave "checkColor" na instância de "UIView". Acertar uma exceção ao tentar definir seu valor: [setValue: forUndefinedKey:]: esta classe não é compatível com a codificação de valor de chave para a chave checkColor.

A forma como resolvi meu problema foi fornecer o módulo com o nome CheckboxButton conforme abaixo:

Nota: você deve substituir CheckboxButton por qualquer nome do módulo que você está usando.

Even Cheng
fonte
4

Resolvi pessoalmente esse problema usando o botão "-" para excluir o conteúdo do meu inspetor de identidade. Quando você remove classes personalizadas, altera o conteúdo no IB e, em seguida, adiciona uma nova classe personalizada, os elementos designáveis ​​no inspetor de identidade não são removidos e isso me causou esse erro. Basta excluir tudo e reconstruir.insira a descrição da imagem aqui

HannahCarney
fonte
Fiz exatamente o que você disse e isso resolveu meu problema. Todas as soluções anteriores expostas aqui não funcionaram. Muito obrigado. ; o)
XLE_22
@ XLE_22 às vezes são as respostas que ninguém olha que resolvem, hein? :)
HannahCarney
Tive um problema em que renomeei uma propriedade IBInspectable em alguns dos meus xib. Depois de fazer isso, recebi vários avisos informando que o XCode não conseguiu encontrar a propriedade agora renomeada. Remover a propriedade do inspetor de identidade corrigiu meu problema.
WBuck
1

Eu sei que isso está respondido, mas aqui está mais uma experiência.

Eu estava tendo alguns problemas não relacionados a esse problema, mas no processo removi @IBInspectable dos vars em minha classe e excluí os atributos do inspetor de identidade (alt-apple-3).

Depois de corrigir o problema (código) com o componente, atualizei tudo várias vezes, mas ainda não havia atributos no inspetor de identidade.

Eventualmente, percebi que eles estavam de volta, mas apenas no inspetor de atributos (alt-apple-4) . Assim que adicionei valores a eles lá, eles reapareceram no inspetor de identidade

Gordon Dove
fonte
1

A resposta de Dave Thomas acima me deu a solução (reversa), quando não dos outros (Dados derivados, Editor> Atualizar), mas por uma questão de clareza, caso as pessoas não tenham certeza de onde editar o XML ... você não não preciso!

  1. Em seu arquivo de storyboard selecione a visão problemática
  2. Na barra lateral direita, selecione a guia Inspetor de identidade (3ª opção da esquerda).
  3. Você terá sua classe personalizada, que já deve estar definida, e o Module. Para mim, isso estava vazio e eu estava recebendo os mesmos erros do OP. Eu defini o Modulecom o nome do meu projeto e BAM - ele começou a funcionar após a reconstrução!
porquecodewhyyyy
fonte
0

Eu acabei de falar sobre esse problema. Tentei todas as coisas listadas aqui e em outros lugares, sem sorte. Este é um storyboard que funcionou bem para sempre e de repente parou de funcionar com o problema "Ignorando atributo de tempo de execução definido pelo usuário ...".

Por alguma razão, remover este código de um dos meus IBDesignable corrigiu:

-(void)viewDidLoad {
    self.clipsToBounds = YES;
}

remover isso fazia com que todos os avisos fossem embora, mesmo em outros objetos IBDesignable. Não tenho ideia de por que essa única etapa corrigiu isso, mas talvez ajude outra pessoa também.

IMFletcher
fonte
3
sua chamada perdida para o jantar aqui
RolandasR
0

Eu estava tendo o mesmo problema e tive que mudar o cornerRadius e o BorderWidth para ser uma String e então convertê-lo para CGFloat, era a única solução para eu poder mudar os valores e ver as mudanças no construtor de interface.

@IBInspectable var borderColor: UIColor? {
    didSet {
        layer.borderColor = borderColor!.CGColor
    }
}

@IBInspectable var borderWidth: String? {
    didSet {
        layer.borderWidth = CGFloat(Int(borderWidth!) ?? 0)
    }
}

@IBInspectable var cornerRadius: String? {
    didSet {
        layer.cornerRadius = CGFloat(Int(cornerRadius!) ?? 0)
        layer.masksToBounds = layer.cornerRadius > 0
    }
}
Chuy47
fonte
Acho que o IBInspectable só pode fazer certos tipos, então talvez você precisasse usar em Floatvez de CGFloate lançar isso
Fonix