Problema semântico: O getter sintetizado da propriedade segue a convenção de nomenclatura do cacau para o retorno de objetos 'de propriedade'

283

Atualmente, estou usando o iOS 5 SDK tentando desenvolver meu aplicativo. Estou tentando criar uma propriedade NSString e sintetizá-la no arquivo .m (já fiz isso antes sem problemas). Agora, me deparei com isso: "Problema semântico: o getter sintetizado da propriedade segue a convenção de nomenclatura do cacau para o retorno de objetos 'de propriedade'".

Este é o meu código: .h

@interface ViewController : UIViewController {
     NSString *newTitle;
}
@property (strong, nonatomic) NSString *newTitle;

.m

@synthesize newTitle;

Alguém tem uma idéia de como eu poderia resolver isso? Obrigado!!

Noam
fonte
Eu tive um erro muito semelhante "A propriedade segue as convenções de nomenclatura do cacau para devolver objetos 'de propriedade'" A resposta de Bavarious abaixo parece resolver isso também.
TMin

Respostas:

606

Meu palpite é que a versão do compilador que você está usando segue também as regras de gerenciamento de memória para propriedades declaradas - mais especificamente, para acessadores de propriedades declaradas:

Você assume a propriedade de um objeto se o criar usando um método cujo nome comece por "alocar", "novo", "copiar" ou "mutableCopy".

Uma propriedade chamada newTitle, quando sintetizada, gera um método chamado -newTitle, daí o aviso / erro. -newTitledeve ser um método getter para a newTitlepropriedade, no entanto, as convenções de nomenclatura afirmam que um método cujo nome começa comnew retorna um objeto que pertence ao chamador, o que não é o caso dos métodos getter.

Você pode resolver isso:

  1. Renomeando essa propriedade:

    @property (strong, nonatomic) NSString *theNewTitle;
  2. Mantendo o nome da propriedade e especificando um nome de getter que não comece com um dos prefixos de nome de método especial:

    @property (strong, nonatomic, getter=theNewTitle) NSString *newTitle;
  3. Mantendo o nome da propriedade e o nome do getter e informando ao compilador que, mesmo que o nome do getter comece com new, ele pertence aonone família de métodos, e não à newfamília de métodos:

    #ifndef __has_attribute
    #define __has_attribute(x) 0  // Compatibility with non-clang compilers
    #endif
    
    #if __has_attribute(objc_method_family)
    #define BV_OBJC_METHOD_FAMILY_NONE __attribute__((objc_method_family(none)))
    #else
    #define BV_OBJC_METHOD_FAMILY_NONE
    #endif
    
    @interface ViewController : UIViewController
    @property (strong, nonatomic) NSString *newTitle;
    - (NSString *)newTitle BV_OBJC_METHOD_FAMILY_NONE;
    @end

    Observe que, embora esta solução permita que você mantenha newTitle o nome da propriedade e o nome do getter, ter um método chamado -newTitleque não retorna um objeto de propriedade do chamador pode ser confuso para outras pessoas que leem seu código.


Para o registro, a Apple publicou Transição para o ARC Release Notes , na qual afirmam:

Você não pode dar um nome a uma propriedade que comece com new ou copy.

Eles já foram notificados de que sua declaração não é muito precisa: o culpado é o nome do método getter, não o nome da propriedade.


Edit 17 Jan 2015: Acabei de notar uma confirmação recente para Clang que sugere a opção 3 acima (usando objc_method_family(none)), incluindo uma correção, para o caso geral em que um nome de propriedade corresponde a um dos prefixos especiais da família de métodos. O Xcode provavelmente incorporará essa alteração eventualmente.

Cœur
fonte
6
Trabalhou como um homem de charme !! Obrigado!!! Para referência futura - usei "@property (forte, não atômica, getter = theNewTitle) NSString * newTitle;"
Noam
8
Resposta maravilhosa. Eu tinha variáveis ​​prefixadas "new".
Eu também tenho esse problema e desperdice muito tempo! Você é realmente um gênio! Obrigado!
H Lai
NS_RETURNS_NOT_RETAINEDé o que você precisa também.
precisa saber é o seguinte
55

Nomes de objetos inaceitáveis

  • newButton
  • copyLabel
  • assignTitle

Nomes de objetos aceitáveis

  • neueButton
  • mCopyLabel
  • _allocTitle

#arc # sintetizado automaticamente # xcode-4.6.1

** EDIT **

Aparentemente, você também não pode usar o mutableCopy .

Jacksonkr
fonte
1
Notei também que "copiar" não pode ser usado a partir de agora.
Rishab 5/02
30

O nome do membro que começa com new é o que aciona o aviso. Altere o nome para EditedTitle e o aviso desaparecerá. Não consegui encontrar documentação confirmando isso, mas, através do teste, foi possível determinar que as variáveis ​​de membro que começam com 'new' agravam o compilador.

Michael
fonte
8

O ARC não permite usar "Novo ...." no nome da propriedade. mas você pode usar "newTitle" alterando o nome do getter.

@property (nonatomic, strong, getter=theNewTitle) NSString *newTitle;
sooop
fonte
6

Não parece o que Bavarious estava sugerindo era o que você queria fazer. Tudo o que você quer fazer é declarar uma variável de instânciaNewTitle e sintetizar a propriedade Costumávamos declarar a variável e a propriedade da instância. Não mais.

Agora, acredito que o caminho certo para fazer isso é o seguinte:

.h

@interface ViewController : UIViewController

@property (nonatomic, strong) NSString *newTitle;

.m

@synthesize newTitle = _newTitle; // Use instance variable _newTitle for storage

A variável de instância para a propriedade newTitleé sintetizada. Você não deseja que sua variável de instância seja igual à sua propriedade - é muito fácil cometer erros .

Consulte o Exemplo: Declarando propriedades e sintetizando acessadores

aquraishi
fonte
Isso depende da versão do compilador. Versões recentes do clang emitem um aviso nesse caso, e é por isso que mencionei a versão do compilador na minha resposta.
Eu não acho que você resolveu o problema. Para o Xcode 9, é um erro, não um aviso. NS_RETURNS_NOT_RETAINEDé o que você precisa.
DawnSong
4

No CoreData, se você usar "novo ..." no atributo (compilar normalmente), ele trava aleatoriamente com uma exceção de "acesso incorreto".

Não há registro de falha e a linha mostrada com o "Ponto de interrupção de todas as exceções" não ajudará em nada.

las
fonte
3

Escrever um setter manualmente com o nome igual ao da propriedade removeu esse aviso.

Serge Rykovski
fonte
No Xcode 7.3, isso não ajudou. Um erro ainda aparece na linha de definição de propriedade.
Arlomedia
1

Além da questão de que você deve / não pode usar "new" na frente de seus nomes de propriedade, digamos mais uma coisa: tente evitar "new" na frente de nomes em geral. "Novo" depende do tempo. Atualmente, é novo para você, mas algum tempo depois você talvez queira implementar algo novo novamente. Portanto, usar "novo" em nomes é sempre ruim. Tente pensar assim: no mundo da programação, "novo" está sempre criando algo: uma nova instância de algo.

No seu caso, quando você deseja atribuir um título diferente, em seguida, o nome atual, sua propriedade titleReplacement.

Mais uma coisa: tente nomear funções e métodos com o verbo primeiro, como setSomething ou getSomething. Porém, nas propriedades, tente nomear o objeto primeiro, como heightMinimum, heightMaximum, etc. -> quando você usa o inspetor durante a codificação, sempre procura objetos. Experimente. ;-)

Philipp Schaller
fonte
1

NS_RETURNS_NOT_RETAINED é usado para resolver o problema de nomeação.

@property (nonatomic, copy) NSString *newTitle NS_RETURNS_NOT_RETAINED;

Podemos encontrar sua definição da seguinte maneira:

#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))

O atributo 'ns_returns_not_retained' é o complemento de 'ns_returns_retained'. Onde uma função ou método pode parecer obedecer às convenções de cacau e retornar um objeto de cacau retido, esse atributo pode ser usado para indicar que a referência de objeto retornada não deve ser considerada como uma referência "proprietária" sendo retornada ao chamador. A estrutura do Foundation define uma macro NS_RETURNS_NOT_RETAINED que é funcionalmente equivalente à mostrada abaixo.

Anexe mais detalhes aqui.

DawnSong
fonte
-2

tente o seguinte: -

@property (nonatomic,retain) NSString *newTitle;
Gypsa
fonte
1
Ainda, o mesmo problema exato. Para sua informação, a linha de erro está na linha @synthesize.
Noam