Problema semántico: el captador sintetizado de la propiedad sigue la convención de nomenclatura de cacao para devolver objetos 'propios'

283

Actualmente estoy usando el SDK de iOS 5 tratando de desarrollar mi aplicación. Estoy tratando de hacer que un NSString sea una propiedad, y luego sintetizarlo en el archivo .m (lo he hecho antes sin problemas). Ahora, me encontré con esto: "Problema semántico: el captador sintetizado de la propiedad sigue la convención de nomenclatura de Cocoa para devolver objetos 'propios'".

Este es mi código: .h

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

.metro

@synthesize newTitle;

¿Alguien tiene idea de cómo podría solucionar esto? ¡¡Gracias!!

Noam
fuente
Tuve un error muy similar "La propiedad sigue las convenciones de nomenclatura de cacao para devolver objetos" propios "" La respuesta de Bavarious a continuación parece resolver esto también.
TMin

Respuestas:

606

Supongo que la versión del compilador que está usando sigue las reglas de administración de memoria para las propiedades declaradas, más específicamente, para los accesores de las propiedades declaradas:

Usted toma posesión de un objeto si lo crea usando un método cuyo nombre comienza con "alloc", "new", "copy" o "mutableCopy".

Una propiedad denominada newTitle, cuando se sintetiza, produce un método llamado -newTitle, de ahí la advertencia / error. -newTitlese supone que es un método getter para la newTitlepropiedad, sin embargo, las convenciones de nomenclatura establecen que un método cuyo nombre comienza con newdevuelve un objeto que pertenece al llamador, que no es el caso de los métodos getter.

Puedes resolver esto de la siguiente manera:

  1. Renombrar esa propiedad:

    @property (strong, nonatomic) NSString *theNewTitle;
  2. Mantener el nombre de la propiedad y especificar un nombre getter que no comience con uno de los prefijos de nombres de métodos especiales:

    @property (strong, nonatomic, getter=theNewTitle) NSString *newTitle;
  3. Mantener tanto el nombre de la propiedad como el nombre del captador, y decirle al compilador que, aunque el nombre del captador comienza con new, pertenece a la nonefamilia de métodos en lugar de a la newfamilia 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

    Tenga en cuenta que aunque esta solución le permite mantener newTitletanto el nombre de la propiedad como el nombre del captador, tener un método llamado -newTitleque no devuelva un objeto propiedad de la persona que llama puede ser confuso para otras personas que leen su código.


Para el registro, Apple ha publicado Transition to ARC Release Notes , en el que declaran:

No puede dar a una propiedad un nombre que comience con newo copy.

Ya se les ha notificado que su declaración no es del todo precisa: el culpable es el nombre del método getter, no el nombre de la propiedad.


Edición 17 de enero de 2015: Acabo de notar un compromiso reciente con Clang que sugiere la opción 3 anterior (usando objc_method_family(none)), incluido un arreglo, para el caso general en el que el nombre de una propiedad coincide con uno de los prefijos de familia de métodos especiales. Xcode probablemente incorporará este cambio eventualmente.

Coeur
fuente
66
Trabajó como un hombre encantador! ¡¡¡Gracias!!! Para referencia futura: utilicé "@property (strong, nonatomic, getter = theNewTitle) NSString * newTitle;"
Noam
8
Maravillosa respuesta. Tenía las variables con el prefijo "nuevo".
¡También tengo este problema y me hace perder mucho tiempo! Eres realmente un genio ~ ¡Gracias!
H Lai
NS_RETURNS_NOT_RETAINEDes lo que necesitas también.
DawnSong
55

Nombres de objetos inaceptables

  • nuevoBotón
  • copyLabel
  • allocTitle

Nombres de objetos aceptables

  • neueButton
  • mCopyLabel
  • _allocTitle

#arc # auto-sintetizado # xcode-4.6.1

** EDITAR **

Aparentemente tampoco puedes usar mutableCopy .

Jacksonkr
fuente
1
También noté que "copiar" no se puede usar a partir de ahora.
Rishab
30

El nombre del miembro que comienza con nuevo es lo que desencadena la advertencia. Cambie el nombre a editedTitle y la advertencia desaparecerá. No pude encontrar documentación que lo confirme, pero a través de las pruebas pude determinar que las variables miembro que comienzan con 'nuevo' agravan el compilador.

Miguel
fuente
8

ARC no permite usar "Nuevo ..." en el nombre de la propiedad. pero puede usar "newTitle" cambiando el nombre del captador.

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

No parece que Bavarious sugiriera que era lo que querías hacer. Todo lo que quiere hacer es declarar una variable de instancia NewTitley luego sintetizar la propiedad. Solíamos tener que declarar la variable de instancia y la propiedad. No más.

Ahora, creo que la forma correcta de hacerlo es la siguiente:

.h

@interface ViewController : UIViewController

@property (nonatomic, strong) NSString *newTitle;

.metro

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

La variable de instancia para la propiedad newTitlese sintetiza. No desea que su variable de instancia sea la misma que su propiedad, demasiado fácil para cometer errores .

Ver ejemplo: Declarar propiedades y sintetizar accesorios

aquraishi
fuente
Eso depende de la versión del compilador. Las versiones recientes de clang emiten una advertencia en este caso, por lo que he mencionado la versión del compilador en mi respuesta.
No creo que hayas resuelto el problema. Para Xcode 9, es un error, no una advertencia. NS_RETURNS_NOT_RETAINEDes lo que necesitas
DawnSong
4

En CoreData si usa "nuevo ..." en el atributo (compilar normalmente) se bloqueará aleatoriamente con una excepción de "mal acceso".

No hay registro de fallas y la línea que se muestra con el "Punto de interrupción de todas las excepciones" no lo ayudará en absoluto.

las
fuente
3

Escribir un setter manualmente con el mismo nombre que la propiedad ha eliminado esta advertencia.

Serge Rykovski
fuente
En Xcode 7.3, esto no ayudó. Todavía aparece un error en la línea de definición de propiedad.
arlomedia
1

Además del problema de que debe / no puede usar "nuevo" delante de sus nombres de propiedad, digamos una cosa más: trate de evitar "nuevo" delante de los nombres en general. "Nuevo" depende del tiempo. Actualmente es nuevo para usted, pero algún tiempo después tal vez quiera implementar algo nuevo nuevamente. Por lo tanto, usar "nuevo" en los nombres siempre es malo. Trate de pensar de esta manera: en el mundo de la programación, "nuevo" siempre está creando algo: una nueva instancia de algo.

En su caso, cuando desee asignar un título diferente, entonces el nombre actual de su título de propiedad Reemplazo.

Una cosa más: primero intente nombrar funciones y métodos con el verbo, como setSomething o getSomething. Pero en las propiedades, intente nombrar el objeto primero, como heightMinimum, heightMaximum, etc. -> cuando usa su inspector cuando está codificando, siempre busca objetos. Pruébalo. ;-)

Philipp Schaller
fuente
1

NS_RETURNS_NOT_RETAINED se usa para resolver el problema de nombres.

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

Podemos encontrar su definición de la siguiente manera,

#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))

El atributo 'ns_returns_not_retained' es el complemento de 'ns_returns_retained'. Cuando una función o método parezca obedecer las convenciones de Cocoa y devolver un objeto Cocoa retenido, este atributo puede usarse para indicar que la referencia de objeto devuelta no debe considerarse como una referencia "propietaria" que se devuelve al llamante. El framework Foundation define una macro NS_RETURNS_NOT_RETAINED que es funcionalmente equivalente a la que se muestra a continuación.

Adjunte más detalles aquí.

DawnSong
fuente
-2

prueba esto:-

@property (nonatomic,retain) NSString *newTitle;
Gypsa
fuente
1
Aún así, el mismo problema exacto. FYI, la línea de error está en la línea @synthesize.
Noam