error: la propiedad atómica grabable no puede emparejar un setter / getter sintetizado con un setter / getter definido por el usuario

128

Recientemente intenté compilar un proyecto Xcode anterior (que solía compilar bien), y ahora veo muchos errores de esta forma:

error: writable atomic property 'someProperty' cannot pair a synthesized setter/getter with a user defined setter/getter

El patrón de código que causa estos errores siempre se ve así:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

@synthesize someProperty; // to provide the getter
- (void)setSomeProperty:(NSObject *)newValue
{
    //..
}

Puedo ver por qué se genera el error. Le digo al compilador que sintetice mis accesores de propiedad (tanto getter como setter), y luego inmediatamente anulo el setter manualmente. Ese código siempre olía un poco mal.

Entonces, ¿cuál es la forma correcta de hacer esto? Si uso en @dynamiclugar de @synthesize, también tendré que escribir el captador. ¿Es esa la única forma?

e.James
fuente
¿Esto solo sucede con las atomicpropiedades? En el caso de las propiedades atómicas, podría ser una buena idea mantener sincronizado el par getter / setter con respecto a la estrategia de bloqueo. Esto es difícil si una parte se sintetiza mientras que la otra es código personalizado.
Nikolai Ruhe
Ciertamente desaparece si hago que la propiedad no sea atómica. Interesante. Ni siquiera había pensado en el problema de sincronización.
e.James
Visité este tema para encontrar una solución a ese problema exacto. Realmente no quiero escribir un getter y un setter solo. Oh, bueno ...
Constantino Tsarouhas
Por defecto, todas las propiedades son atómicas y debemos hacerlas explícitamente no atómicas. Las propiedades atómicas son seguras para subprocesos, por lo que no podemos implementar setter y getter para ellas porque cambiará su funcionalidad segura para subprocesos. Espero que entiendas el motivo por el que recibes este error.
Mohd Haider

Respuestas:

218

Tuve el mismo problema y después de investigar un poco, aquí está mi conclusión sobre este problema:

El compilador le advierte sobre una @propertydeclaración que declaró como atómica (es decir, al omitir la nonatomicpalabra clave), pero proporciona una implementación incompleta de cómo sincronizar el acceso a esa propiedad.

Para hacer desaparecer esa advertencia:

Si declara que @propertya es atómico, realice una de las siguientes acciones:

  • usar @dynamico;
  • usar @synthesizey mantener el setter y getter sintetizado o;
  • Proporcionar una implementación manual tanto del configurador como del getter (sin utilizar una de las directivas anteriores).

Si declara @propertycon with (nonatomic), puede mezclar implementaciones manuales y sintetizadas de getters y setters.

Actualización: una nota sobre la síntesis automática de propiedades

A partir de LLVM 4.0, CLang proporciona síntesis automática para propiedades declaradas que no lo son @dynamic. Por defecto, incluso si omite el @synthesize, el compilador le proporcionará métodos getter y setter. Sin embargo, la regla para las propiedades atómicas sigue siendo la misma: ¡Deje que el compilador proporcione tanto el captador como el definidor, O implemente ambos usted mismo!

octy
fuente
¡Gracias! "declarar la propiedad @ con (no atómica)"
Nianliang
14

Necesitas implementar el getter también. Ejemplo:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

- (void)setSomeProperty:(NSObject *)newValue
{
    @synchronized (self)
    {
        // ...
    }
}

- (NSObject *)someProperty
{
    NSObject *ret = nil;

    @synchronized (self)
    {
        ret = [[someProperty retain] autorelease];
    }

    return ret;
}
arturgrigor
fuente
12

Esta pregunta, entre los otros éxitos principales que obtiene al buscar "propiedad personalizada del objetivo C", no se actualiza con información sobre "setter =" o "getter =".

Entonces, para proporcionar más información sobre esta pregunta:

Puede proporcionar la llamada a @property con su propio método escribiendo

    @property(setter = MySetterMethod:, getter = MyGetterMethod)

Observe los dos puntos para el método de establecimiento proporcionado.

Referencia de documentación de Apple

EDITAR: No estoy muy seguro de cómo los nuevos cambios en las propiedades de Objective-C (ahora son mucho más inteligentes) cambian las respuestas a esta pregunta. Quizás todo debería estar marcado como desactualizado.

Matias Forbord
fuente
Descubrí que configurar el método setter en realidad no eliminó la advertencia. por ejemplo -> "@property (asignar, establecer = setDelegate :) id delegate;" En este caso, todo lo que puedo hacer es agregar mi propio captador o agregar la propiedad no atómica, lo cual no estoy seguro si debería, dado que estoy configurando el delegado 'atómicamente', no importa tener la propiedad no atómica o eso entiendo.
David van Dugteren
Interesante, David. ¿En qué "versión" de Objective-C se encuentra esto (supongo que decir que la versión XCode sería más útil)? No estoy seguro de cuáles son los cambios recientes en Objective-C, específicamente con iOS 6.
Matias Forbord
0

Para otros que reciben este error, no por la razón que describió OP, es probable que tengan el mismo problema que yo:

Tiene una propiedad @ con el mismo nombre que un método - ().

Algo como esto:

@property UIView *mainView;

-(UIView *)mainView;
Albert Renshaw
fuente