Eu declarei uma propriedade somente leitura em minha interface como tal:
@property (readonly, nonatomic, copy) NSString* eventDomain;
Talvez eu esteja entendendo mal as propriedades, mas pensei que, quando você declara como readonly
, pode usar o setter gerado dentro do .m
arquivo de implementação ( ), mas as entidades externas não podem alterar o valor. Esta pergunta do SO diz que é isso que deve acontecer. Esse é o comportamento que procuro. No entanto, ao tentar usar o setter padrão ou sintaxe de ponto para definir eventDomain
dentro do meu método init, recebo um unrecognized selector sent to instance.
erro. Claro que estou @synthesize
roubando a propriedade. Tentando usá-lo assim:
// inside one of my init methods
[self setEventDomain:@"someString"]; // unrecognized selector sent to instance error
Então, estou interpretando mal a readonly
declaração de uma propriedade? Ou algo mais está acontecendo?
.h
? Caso contrário, não vejo como isso exporia um setter público. ObrigadoEiko e outros deram respostas corretas.
Esta é uma maneira mais simples: Acesse diretamente a variável de membro privado.
Exemplo
No arquivo .h do cabeçalho:
@property (strong, nonatomic, readonly) NSString* foo;
No arquivo .m de implementação:
É isso, é tudo de que você precisa. Sem confusão, sem confusão.
Detalhes
A partir do Xcode 4.4 e do LLVM Compiler 4.0 ( novos recursos no Xcode 4.4 ), você não precisa mexer nas tarefas discutidas nas outras respostas:
synthesize
palavra-chaveDepois de declarar uma propriedade
foo
, você pode assumir Xcode acrescentou uma variável de membro particular chamado com um prefixo de sublinhado:_foo
.Se a propriedade foi declarada
readwrite
, o Xcode gera um método getter chamadofoo
e um setter chamadosetFoo
. Esses métodos são chamados implicitamente quando você usa a notação de ponto (meu Object.myMethod). Se a propriedade foi declaradareadonly
, nenhum setter é gerado. Isso significa que a variável de apoio, nomeada com o sublinhado, não é somente leitura. Osreadonly
meios simplesmente que nenhum método de ajuste foi sintetizada, e, portanto, usando a notação de pontos para definir um valor de falha com um erro do compilador. A notação de ponto falha porque o compilador o impede de chamar um método (o setter) que não existe.A maneira mais simples de contornar isso é acessar diretamente a variável de membro, nomeada com o sublinhado. Você pode fazer isso mesmo sem declarar essa variável com nome de sublinhado! O Xcode está inserindo essa declaração como parte do processo de construção / compilação, então seu código compilado realmente terá a declaração da variável. Mas você nunca vê essa declaração em seu arquivo de código-fonte original. Não mágico, apenas açúcar sintático .
Usar
self->
é uma forma de acessar uma variável de membro do objeto / instância. Você pode omitir isso e apenas usar o nome var. Mas eu prefiro usar a seta self + porque ela torna meu código autodocumentado. Quando você vê o,self->_foo
você sabe sem ambigüidade que_foo
é uma variável de membro nesta instância.By the way, discussão de prós e contras de assessores da propriedade versus acesso Ivar direta é exatamente o tipo de tratamento pensativo você vai ler na Dr. Matt Neuberg 's Programming iOS livro. Achei muito útil ler e reler.
fonte
readonly
tal que nenhuma outra classe pode defini-la.Outra maneira que descobri de trabalhar com propriedades somente leitura é usar @synthesize para especificar o armazenamento de apoio. Por exemplo
Então, na implementação
Seus métodos podem então definir
m_whatever
, uma vez que é uma variável de membro.Outra coisa interessante que percebi nos últimos dias é que você pode criar propriedades somente leitura que podem ser gravadas por subclasses como:
(no arquivo de cabeçalho)
Então, na implementação
Ele usará a declaração no arquivo de cabeçalho, de forma que as subclasses possam atualizar o valor da propriedade, enquanto retém sua leitura somente.
No entanto, um pouco lamentavelmente em termos de ocultação e encapsulamento de dados.
fonte
Consulte Personalização de classes existentes nos documentos do iOS.
As propriedades somente leitura têm apenas um método getter. Você ainda pode definir o ivar de apoio diretamente na classe da propriedade ou usando a codificação de valor-chave.
fonte
Você está entendendo mal a outra questão. Nessa questão há uma extensão de classe, declarada assim:
Isso é o que gera o setter visível apenas na implementação da classe. Portanto, como diz Eiko, você precisa declarar uma extensão de classe e substituir a declaração de propriedade para dizer ao compilador para gerar um setter apenas dentro da classe.
fonte
A solução mais curta é:
MyClass.h
MyClass.h
fonte
Se uma propriedade for definida como somente leitura, isso significa que efetivamente não haverá um configurador que possa ser usado internamente para a classe ou externamente para outras classes. (ou seja: você só terá um "getter" se isso fizer sentido.)
Pelo que parece, você deseja uma propriedade normal de leitura / gravação marcada como privada, que pode ser obtida definindo a variável de classe como privada em seu arquivo de interface da seguinte forma:
fonte