2009-09-16 10 views
5

Estoy creando una clase base que tiene un indicador isDirty. Se establece cada vez que una de sus propiedades cambia, pero como es una clase base, no sabe cuáles son sus propiedades. Así que, básicamente, en cada subclase, tengo que anular cualquier - set: método para algo como esto:¿Puedo omitir el funcionamiento de @synthesize en Objective C?

- (id) setName:(NSString *)value { 
    if ([name isEqualToString:value]) { 
    return; 
    } 
    [name autorelease]; 
    name = [value retain]; 
    isDirty = YES; //Here's the important bit 
} 

casi todas las líneas de eso es lo que el colocador sintetizado automáticamente haría. ¿Hay alguna manera de que pueda anular lo que realmente crea @synthesize?

Hay otras opciones que se me han ocurrido, pero todas parecen ser mucho más lentas en tiempo de ejecución que este método. He pensado en cosas como agregar un objeto para observar sus propios cambios de propiedad, o crear una función genérica para hacer todo eso y simplemente pasar la dirección al iVar y el nuevo valor, pero eso todavía requiere anular el setter.

¿Alguna idea? Si hace una diferencia, es para una aplicación de iPhone.

+0

Por favor, presente un error a través de http://bugreport.apple.com/ solicitando la posibilidad de anular @synthesize. Copie la URL a esta página o solo el contenido de su pregunta. Gracias. – bbum

Respuesta

7

No hay forma de que sepa que le permite anular lo que hace @synthesize.

Al final del día, se usa para crear métodos básicos de acceso, es decir. aquellos que no tienen un comportamiento específico.

Tal vez deberías consultar la codificación del valor clave y la observación del valor clave?

+0

Como mencioné, había pensado en observar los cambios, pero sería más lento que hacerlo de la forma en que lo estoy ahora, así que me ocuparé de ello. –

+0

Nuevamente, ¿lo has medido realmente? Si su método -setName: se está llamando tan a menudo que KVO es una carga medible, es muy probable que haya un defecto de diseño grave en su aplicación. – bbum

+0

No es solo -setName, obviamente. Como dije, estoy diseñando una clase base que puede tener cualquier subclase de objeto con cualquier variable. –

8

varios problemas aquí:

(1) Si usted está preocupado por el rendimiento de la moda, no se debe utilizar -isEqualToString: en su colocador. En su lugar, compara un puntero porque eso es todo lo que importa en este contexto.

(2) Si tiene un atributo NSString, debe copiar en el conjunto. La copia es gratuita para cadenas inmutables y guardará su tocino para cuerdas mutables (evitando que la persona que llama mute la cuerda debajo de usted).

(3) De nuevo con rendimiento; revisaste la igualdad, pero luego utilizas la liberación automática. Eso incurre en gastos generales innecesarios.

(4) * todos parecen ser mucho más lentos en el tiempo de ejecución * indica que no lo ha intentado realmente, no ha identificado un problema de rendimiento y está optimizando prematuramente su código. Dado (1) y (3), es probable que haya problemas de rendimiento mucho más fáciles de abordar.

Mis sugerencias:

(1) Utilice @synthesize. Generará código correcto y rápido, direccionamiento (1) y (3).

(2) Utilice KVO o uno de los otros mecanismos. Hasta que identifica un problema de rendimiento mediante la instrumentación y la cuantificación, no tiene un problema de rendimiento.

(3) Considere usar CoreData (a menos que, por supuesto, esté apuntando a OS 2.x). El código de ejemplo proviene de algo que obviamente es un objeto modelo.Si su código está bien factorizado en el modelo/vista/controlador, el uso de CoreData en la capa del modelo puede simplificar su aplicación y CoreData hace un trabajo maravilloso de seguimiento de cambios.

+0

En cuanto a 1, estoy usando isEqualToString porque si son cadenas diferentes que tienen los mismos contenidos, no quiero establecer el indicador de isDirty. No he probado otros métodos, pero me parece de sentido común que enviar más mensajes significa que lleva más tiempo. ¿No crees? –

+1

No hasta que lo mida. Enviar una copia a cadenas inmutables, incluso cuando se copia el valor que ya estaba allí, va a ser más rápido que llamar -isEqualToString; en dos cadenas inmutables diferentes. – bbum

+0

(A menos que, por supuesto, la respuesta a isDirty: sea significativamente costosa. Si ese es el caso, entonces es mejor que vuelva a visitar por qué su código está restableciendo el mismo valor. – bbum

1

Si escribe su propio método (s) de acceso @synthesize respeta eso. @synthesize da prioridad a los accesores que escribe por su cuenta. Simplemente proporcione el acceso que desee y @synthesize se ignorará en ese. Por ejemplo, podría implementar un descriptor de acceso que cree la propiedad solo en caso de que todavía no esté allí.

Ejemplo:

@synthesize standardUserDefaults; 

- (NSUserDefaults *)standardUserDefaults { 
    NSLog(@"standardUserDefaults"); 
    if (!standardUserDefaults) { 
     NSLog(@"standardUserDefaults new"); 
     self.standardUserDefaults = [NSUserDefaults standardUserDefaults]; 
    } 
    return standardUserDefaults; 
} 

Aquí el "setter" se sintetiza, mientras que el "getter" no lo es.

+0

Eso no es exactamente lo que estaba buscando en ese momento. No quería tener que escribir un método setter para cada propiedad, pero solo escriba un método único que usaría cada propiedad cuando se sintetice el colocador, que es, de hecho, imposible, hasta donde yo sé. –

+0

En ese caso, Key-Value-Observing y using keyPathsForValuesAffectingValueForKey: podrían ser útiles. Ver http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueObserving_Protocol/Reference/Reference.html#//apple_ref/occ/clm/NSObject/keyPathsForValuesAffectingValueForKey: – MacMark

+0

Estoy bastante seguro de que todavía no es lo que estaba buscando. Sin embargo, te invitaría a dar una muestra de cómo eso funcionaría y satisfaría mis necesidades. –

Cuestiones relacionadas