¿Cuál es la mejor manera de utilizar Obj-C 2.0 Properties con objetos mutables, como NSMutableArray?

Tengo una clase Obj-C 2.0 que tiene una propiedad NSMutableArray. Si uso el siguiente código, el setter sintetizado me dará una copia inmutable, no mutable:

@property (readwrite, copy) NSMutableArray *myArray; 

¿Hay alguna razón por la que Apple no implementó la siguiente syntax?

 @property (readwrite, mutablecopy) NSMutableArray *myArray; 

Como no tenemos mutablecopy , ¿cuál es la mejor forma de manejar esta situación (aparentemente común)? ¿Debo simplemente escribir mi propio setter que hace un -mutableCopy?

Como se dijo antes, la forma correcta de hacerlo no es hacer de la matriz mutable una propiedad. Hay una gran explicación de lo que debe implementar para cumplir con KVC aquí .

Me encontré con el mismo problema hace algún tiempo y encontré un documento en el Apple Developer Connection que recomienda proporcionar tu propia implementación del setter. Ejemplo de código del documento vinculado:

 @interface MyClass : NSObject { NSMutableArray *myArray; } @property (nonatomic, copy) NSMutableArray *myArray; @end @implementation MyClass @synthesize myArray; - (void)setMyArray:(NSMutableArray *)newArray { if (myArray != newArray) { [myArray release]; myArray = [newArray mutableCopy]; } } 

No es común pasar NSMutableArray s en Cocoa. La práctica estándar de Cocoa sería implementar los métodos que cumplan con la encoding de clave-valor para una propiedad indexada a-muchos. Esto tiene dos beneficios:

  1. La observación de valores clave funciona como se espera (hay varios casos en los que la observación de un NSMutableArray conduce a un comportamiento distinto de lo que se quiere)
  2. La implementación de su estructura de datos está oculta porque expone los métodos de mutación (por ejemplo -[MyObject insertObjectInMyProperty:(id)newObject atIndex:(NSUInteger)i] , no la estructura de datos en sí.

Tenga en cuenta que pasar alrededor de una matriz mutable no es una práctica común en Cocoa. Puede usar una matriz mutable privada como almacenamiento interno, pero cree métodos usando objetos simples NSArray para agregar u obtener objetos de ella. Esta puede ser la razón por la cual no hay una statement de propiedad de mutablecopy.

Tendrás que escribir tu propio setter.

La forma correcta de aferrarse a un NSMutableArray es con una propiedad retener:

 @property (nonatomic, retain) NSMutableArray *myArray; 

No necesita escribir su propio setter o usar copia. La propiedad de copia se debe usar con un NSArray que realmente necesita copiarse cuando la propiedad se captura en otro objeto. Por ejemplo, si asigna un objeto NSMutableArray a una propiedad que es de tipo NSArray con la propiedad de copia, entonces desea hacer una copia de la matriz mutable para “capturarla” como una propiedad inmutable desde ese punto en adelante.

Y Marc tiene el enfoque correcto, uno normalmente no haría NSMutableArray una parte de la API pública de sus objetos. Si tiene una propiedad pública, puede ser una NSArray con la propiedad de copia.