No momento, estou criando um aplicativo que terá vários temporizadores, que são basicamente iguais.
Eu quero criar uma classe personalizada que usa todo o código para os temporizadores, bem como o layout / animações, para que eu possa ter 5 temporizadores idênticos que operam independentemente um do outro.
Criei o layout usando IB (xcode 4.2) e todo o código para os temporizadores está atualmente apenas na classe viewcontroller.
Estou tendo dificuldade para entender como encapsular tudo em uma classe personalizada e, em seguida, adicioná-la ao viewcontroller, qualquer ajuda seria muito apreciada.
UITableViewCell
ouUICollectionViewCell
. No meu caso, preciso de uma visão pequena, mas bastante complexa, que possa usar muitas vezes em controladores e visualizações de coleção. E os designers continuam retrabalhando, então eu quero um único lugar onde o layout seja definido. Portanto, um bico.Respostas:
Bem, para responder conceitualmente, seu cronômetro provavelmente deve ser uma subclasse de em
UIView
vez deNSObject
.Para instanciar uma instância do seu temporizador no IB, simplesmente arraste e
UIView
solte-o na visualização do seu controlador de visualização e defina sua classe com o nome da classe do seu temporizador.Lembre-se de
#import
sua classe de cronômetro em seu controlador de visualização.Editar: para design IB (para instanciação de código, consulte o histórico de revisão)
Não estou muito familiarizado com o storyboard, mas sei que você pode construir sua interface em IB usando um
.xib
arquivo que é quase idêntico ao da versão do storyboard; Você deve até mesmo ser capaz de copiar e colar suas visualizações como um todo da interface existente para o.xib
arquivo.Para testar isso, criei um novo vazio
.xib
chamado "MyCustomTimerView.xib". Em seguida, adicionei uma visualização e a ela adicionei um rótulo e dois botões. Igual a:Criei uma nova subclasse de classe Objectiva C
UIView
chamada "MyCustomTimer". No meu,.xib
eu defini minha classe Proprietário do arquivo como MyCustomTimer . Agora estou livre para conectar ações e tomadas como qualquer outra visualização / controlador. O.h
arquivo resultante tem a seguinte aparência:O único obstáculo que falta superar é colocar isso
.xib
na minhaUIView
subclasse. Usar um.xib
reduz drasticamente a configuração necessária. E como você está usando storyboards para carregar os cronômetros, sabemos que-(id)initWithCoder:
é o único inicializador que será chamado. Então, aqui está a aparência do arquivo de implementação:O método nomeado
loadNibNamed:owner:options:
faz exatamente o que parece. Ele carrega o Nib e define a propriedade "Proprietário do arquivo" como self. Extraímos o primeiro objeto do array e essa é a visão raiz do Nib. Adicionamos a visualização como uma subvisualização e Voila está na tela.Obviamente, isso apenas muda a cor de fundo do rótulo quando os botões são pressionados, mas este exemplo deve ajudá-lo no bom caminho.
Notas baseadas em comentários:
É importante notar que, se você está tendo problemas de recursão infinita, provavelmente não percebeu o truque sutil dessa solução. Não está fazendo o que você pensa que está fazendo. A visão que é colocada no storyboard não é vista, mas em vez disso carrega outra visão como uma subvisualização. A visualização que ele carrega é a visualização definida na ponta. O "proprietário do arquivo" na ponta é aquela visão invisível. A parte legal é que essa visão invisível ainda é uma classe Objective-C que pode ser usada como uma espécie de controlador de visão para a visão que ela traz da ponta. Por exemplo, os
IBAction
métodos naMyCustomTimer
classe são algo que você esperaria mais em um controlador de visualização do que em uma visualização.Como uma observação lateral, alguns podem argumentar que isso quebra
MVC
e eu concordo um pouco. Do meu ponto de vista, está mais relacionado a um costumeUITableViewCell
, que às vezes também precisa ser parte do controlador.É importante notar também que essa resposta foi para fornecer uma solução muito específica; crie uma ponta que pode ser instanciada várias vezes na mesma visualização em um storyboard. Por exemplo, você pode facilmente imaginar seis desses temporizadores, todos em uma tela de iPad ao mesmo tempo. Se você só precisa especificar uma visualização para um controlador de visualização que deve ser usado várias vezes em seu aplicativo, a solução fornecida por jyavenard para esta questão é quase certamente uma solução melhor para você.
fonte
userInfo
propriedade na notificação@property(nonatomic,copy) NSDictionary *userInfo;
File's Owner
se de que está definido com o nome da classe resolveu meu problema de recursão infinita.[self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"MyCustomTimerView" owner:self options:nil] objectAtIndex:0]];
adicionando o segundo UIView ... Isso parece meio estranho para mim, ninguém mais se sente da mesma maneira? Se sim, isso é algo feito pela maçã por design? Ou alguém encontrou a solução ao fazer isso?Exemplo rápido
Atualizado para Xcode 10 e Swift 4
Aqui está um guia básico. Eu originalmente aprendi muito sobre isso assistindo a esta série de vídeos no Youtube . Posteriormente, atualizei minha resposta com base neste artigo .
Adicionar arquivos de visualização personalizada
Os dois arquivos a seguir formarão sua visualização personalizada:
UIView
subclasseOs detalhes para adicioná-los estão abaixo.
Arquivo Xib
Adicione um arquivo .xib ao seu projeto (Arquivo> Novo> Arquivo ...> Interface do usuário> Exibir) . Estou chamando o meu
ReusableCustomView.xib
.Crie o layout que você deseja que a exibição personalizada tenha. Como exemplo, farei um layout com a
UILabel
e aUIButton
. É uma boa ideia usar o layout automático para que as coisas sejam redimensionadas automaticamente, não importando o tamanho definido posteriormente. (Usei Freeform para o tamanho xib no inspetor de atributos para poder ajustar as métricas simuladas, mas isso não é necessário.)Arquivo Swift
Adicione um arquivo .swift ao seu projeto (Arquivo> Novo> Arquivo ...> Código-fonte> Arquivo Swift) . É uma subclasse de
UIView
e estou chamando de minhaReusableCustomView.swift
.Faça do arquivo Swift o proprietário
Volte para o arquivo .xib e clique em "Proprietário do arquivo" no esboço do documento. No Inspetor de identidade, escreva o nome do seu arquivo .swift como o nome da classe personalizada.
Adicionar código de visualização personalizada
Substitua o
ReusableCustomView.swift
conteúdo do arquivo pelo seguinte código:Certifique-se de usar a grafia correta para o nome do arquivo .xib.
Conecte os Outlets e Ações
Conecte os pontos de venda e ações ao arrastar o controle do rótulo e botão no layout xib para o código de visualização personalizada rápida.
Use sua visualização personalizada
Sua visualização personalizada está concluída agora. Tudo o que você precisa fazer é adicionar um
UIView
onde quiser em seu storyboard principal. Defina o nome da classe da visualizaçãoReusableCustomView
no Identity Inspector.fonte
Bundle.main
paraBundle(for: ...)
resolve. Aparentemente,Bundle.main
não está disponível em tempo de design.init(frame:)
. Depois de adicionar isso (e colocar todo o código de inicialização em algumacommonInit()
função), ele funciona bem e é exibido em IB. Veja mais informações aqui: stackoverflow.com/questions/31265906/…Resposta para controladores de visualização, não visualizações :
Existe uma maneira mais fácil de carregar um xib de um storyboard. Digamos que seu controlador seja do tipo MyClassController do qual herda
UIViewController
.Você adiciona um
UIViewController
usando IB em seu storyboard; mude o tipo de classe para MyClassController. Exclua a visualização que foi adicionada automaticamente ao storyboard.Certifique-se de que o XIB que você deseja chamar se chama MyClassController.xib.
Quando a classe for instanciada durante o carregamento do storyboard, o xib será carregado automaticamente. A razão para isso é devido à implementação padrão
UIViewController
que chama o XIB nomeado com o nome da classe.fonte
'Could not load NIB in bundle: 'NSBundle </Users/me/.../MyAppName.app> (loaded)' with name 'uB0-aR-WjG-view-4OA-9v-tyV''
. Observe o whacko nibName. Estou usando o nome de classe correto para o na ponta.Esta não é realmente uma resposta, mas acho que é útil compartilhar essa abordagem.
Objective-C
Rápido
Opcional:
É tudo, agora você pode adicionar sua visualização personalizada ao storyboard e ela será exibida :)
CustomViewWithXib.h :
CustomViewWithXib.m :
CustomViewWithXib.swift :
Você pode encontrar alguns exemplos aqui .
Espero que ajude.
fonte