Estou interessado em entender as circunstâncias que levam um desenvolvedor a substituir + inicializar ou + carregar. A documentação deixa claro que esses métodos são chamados para você pelo tempo de execução Objective-C, mas isso é realmente tudo o que fica claro na documentação desses métodos. :-)
Minha curiosidade vem de olhar para o código de exemplo da Apple - MVCNetworking. Sua classe modelo tem um +(void) applicationStartup
método. Ele faz alguma manutenção no sistema de arquivos, lê NSDefaults, etc etc ... e, depois de tentar grok os métodos de classe de NSObject, parece que este trabalho de zeladoria pode ser colocado + carregar.
Eu modifiquei o projeto MVCNetworking, removendo a chamada no App Delegate para + applicationStartup e colocando os bits de manutenção em + carga ... meu computador não pegou fogo, mas isso não significa que está correto! Espero obter uma compreensão de todas as sutilezas, pegadinhas e outras coisas em torno de um método de configuração personalizado que você precisa chamar versus + carregar ou + inicializar.
Para + carregar a documentação diz:
A mensagem de carregamento é enviada para classes e categorias que são carregadas dinamicamente e vinculadas estaticamente, mas apenas se a classe ou categoria carregada recentemente implementar um método que possa responder.
Esta frase é confusa e difícil de analisar se você não souber o significado preciso de todas as palavras. Socorro!
O que significa "carregado dinamicamente e vinculado estaticamente?" Algo pode ser carregado dinamicamente E vinculado estaticamente ou são mutuamente exclusivos?
"... a classe ou categoria carregada recentemente implementa um método que pode responder" Que método? Responder como?
Quanto a + inicializar, a documentação diz:
inicializá-lo é invocado apenas uma vez por classe. Se você deseja realizar inicialização independente para a classe e para categorias da classe, você deve implementar métodos de carregamento.
Eu entendo que isso significa, "se você está tentando configurar a classe ... não use inicializar." OK tudo bem. Quando ou por que eu substituiria a inicialização?
fonte
+load
é enviado separadamente para as categorias; ou seja, cada categoria em uma classe pode conter seu próprio+load
método.initialize
será chamado corretamente por umload
método, se necessário, devido àload
referência feita à entidade não inicializada. Isso pode (estranhamente, mas sensatamente) levar a umainitialize
corrida antesload
! Isso é o que tenho observado, de qualquer maneira. Isso parece ser contrário a "E no momento em que você receberinitialize
, todas as aulas em seu processo já devem ter recebidoload
(se apropriado)."load
primeiro. Você pode então receberinitialize
enquantoload
ainda está em execução.Isso significa que não substitua
+initialize
em uma categoria, você provavelmente quebrará algo.+load
é chamado uma vez por classe ou categoria que implementa+load
, assim que essa classe ou categoria é carregada. Quando diz "estaticamente vinculado", significa compilado no binário do seu aplicativo. Os+load
métodos nas classes assim compiladas serão executados quando seu aplicativo for iniciado, provavelmente antes de entrarmain()
. Quando diz "carregado dinamicamente", significa carregado por meio de pacotes de plug-ins ou uma chamada paradlopen()
. Se você estiver no iOS, pode ignorar esse caso.+initialize
é chamado na primeira vez que uma mensagem é enviada para a turma, logo antes de lidar com essa mensagem. Isso (obviamente) só acontece uma vez. Se você substituir+initialize
em uma categoria, uma das três coisas acontecerá:É por isso que você nunca deve substituir
+initialize
em uma categoria - na verdade, é muito perigoso tentar substituir qualquer método em uma categoria porque você nunca tem certeza do que está substituindo ou se sua própria substituição será substituída por outra categoria.BTW, outra questão a ser considerada
+initialize
é que se alguém criar uma subclasse de você, você será potencialmente chamado uma vez para sua classe e uma vez para cada subclasse. Se estiver fazendo algo como configurarstatic
variáveis, você vai querer se proteger contra isso: comdispatch_once()
ou por meio de testesself == [MyClass class]
.fonte