2009-07-01 5 views
9

Quiero crear un NSArray con objetos del mismo valor (digamos NSNumber todo inicializado en 1) pero el recuento se basa en otra variable. No parece haber una manera de hacer esto con ninguno de los inicializadores para NSArray, excepto uno que se ocupa de la matriz C-style.Creando un NSArray inicializado con conteo N, todos del mismo objeto

¿Alguna idea de si hay una manera corta de hacer esto?

Esto es lo que estoy buscando:

NSArray *array = [[NSArray alloc] initWithObject:[NSNumber numberWithInt:0] 
              count:anIntVariable]; 

NSNumber es sólo un ejemplo aquí, en esencia podría ser cualquier NSObject.

Respuesta

3

No veo ninguna razón por la cual esta estructura en un formato no mutable sería útil, pero estoy seguro de que tiene sus razones.

no creo que usted tiene más remedio que utilizar un NSMutableArray, construirlo con un bucle, y si es realmente importante que el resultado no sea mutable, construir un NSArray y utilizar arrayWithArray:

+2

Para obtener una copia inmutable, solo use -copy, que devuelve una matriz con retención de conteo 1 (y no se libera automáticamente). –

+2

En realidad, -copy devuelve una matriz inmutable que usted posee y debe liberar/liberar automáticamente - el conteo de retención podría ser cualquier cosa dependiendo de cuántas matrices idénticas haya. Lo mejor es nunca hablar de retener los conteos. –

+1

Una excelente distinción: estoy corregido. En general, una copia devuelve un objeto recién inicializado que usted solo posee, pero la semántica en una situación específica puede dictar lo contrario. Si bien el recuento de retención suele ser 1, * podría * ser mayor, y otra persona * podría * haberlo liberado automáticamente. Por lo tanto, tiene razón en que lo mejor es solo preocuparse por equilibrar las propias llamadas para retener/liberar/liberar automáticamente. –

2

Estoy de acuerdo con @mmc, asegúrese de tener una razón válida para tener dicha estructura (en lugar de usar el mismo objeto N veces), pero supongo que sí.

Hay otra manera de construir una matriz inmutable que sería un poco más rápido, pero requiere la creación de una matriz C de los objetos y de pasarlo al método de NSArray +arrayWithObject:count: (que devuelve una matriz autoreleased, que conste) de la siguiente manera:

id anObject = [NSNumber numberWithInt:0]; 
id* buffer = (id*) malloc(sizeof(id) * anIntVariable); 
for (int i = 0; i < anIntVariable; i++) 
    buffer[i] = anObject; 
NSArray* array = [NSArray arrayWithObjects:buffer count:anIntVariable]; 
free(buffer); 

Puede lograr lo mismo incluso con el puntero más matemático, pero las ganancias son bastante triviales. Comente si está interesado de todos modos.

+0

Mi conocimiento es un poco incompleto, así que corrígeme si estoy equivocado, pero ¿no causaría esto que todos los elementos de * array sean el mismo objeto NSNumber, y no diferentes objetos inicializados con el mismo valor? Supongo que no debería importar de todos modos ya que NSNumber es inmutable, pero bueno, es lo que Boon pidió. – alanlcode

+0

@alanlcode: Probablemente esto sea irrelevante, ya que [NSNumber numberWithInt: 0] casi seguro devuelve un singleton de todos modos. No hay forma de garantizar punteros únicos para NSNumber *, así que de cualquier manera lo harías, tendrías que lidiar con ese problema, y ​​si es un problema, entonces realmente tendrías que construir tu propia clase con semántica que permitiera dos objetos para ser diferentes y, sin embargo, representan el mismo número. –

+0

Muy cierto. Además, las instancias de NSValue (y NSNumber que subclases) son inmutables, por lo que no tiene sentido tener N objetos del mismo valor; tener el mismo objeto en cada índice es funcionalmente el mismo y usa menos memoria. Si es realmente curioso, intente hacer una copia y una restauración cada vez que inserte el objeto y vea si las instancias son diferentes. Nunca tuve razones para hacer algo como esto yo mismo. –

2

Probablemente la razón por la que no existe dicho método en NSArray es que la semántica no está bien definida. Para su caso, con un NSNumber inmutable, entonces todas las semánticas diferentes son equivalentes, pero imagine si el objeto que estaba agregando era un objeto mutable, como NSMutableString, por ejemplo.

Hay tres diferentes: la semántica

  • retienen - Terminarías con diez punteros a la misma cadena mutable, y el cambio de cualquiera tendría que cambiar los diez.

  • copia - Terminarías con diez punteros a la misma cadena inmutable, o posiblemente diez diferentes punteros a immeduable cadenas con el mismo valor, pero de cualquier manera no sería capaz de cambiar cualquiera de ellas .

  • mutableCopy - Terminas con diez objetos de cadena mutables diferentes, cualquiera de los cuales puedes cambiar de forma independiente.

Así que Apple podría escribir tres variantes del procedimiento, o tener algún tipo de parámetro para controlar la semántica, ambos de los cuales son feos, así que en vez de que lo dejó a usted para escribir el código. Si lo desea, puede agregarlo como un método de categoría NSArray, solo asegúrese de comprender las opciones semánticas y dejarlo en claro.

El método:

-(id)initWithArray:(NSArray *)array copyItems:(BOOL)flag 

tiene esta misma edición.

Solución de Quinn que usa arrayWithObjects: count: es razonablemente buena, probablemente lo mejor que se puede obtener para el caso general. Póngalo en una categoría NSArray y eso es casi tan bueno como lo que va a obtener.

14

El código más apretado que he sido capaz de escribir para esto es:

id numbers[n]; 
for (int x = 0; x < n; ++x) 
    numbers[x] = [NSNumber numberWithInt:0]; 
id array = [NSArray arrayWithObjects:numbers count:n]; 

Esto funciona porque puede crear la longitud de tiempo de ejecución que determine C-arrays con C99, que Xcode usa por defecto.

Si todos son del mismo valor, también se puede utilizar memset (aunque el elenco de int es traviesa):

id numbers[n]; 
memset(numbers, (int)[NSNumber numberWithInt:0], n); 
id array = [NSArray arrayWithObjects:numbers count:n]; 

Si conoce el número de objetos que necesita, entonces este código debe trabajo , aunque no lo he probado:

id array = [NSArray arrayWithObjects:(id[5]){[NSNumber numberWithInt:0]} count:5]; 
+0

ah, gracias brewmaster por el último. –

+0

¿Cómo funciona el último? ¿No estás lanzando una matriz que contiene un solo elemento a una matriz con 5? – bcattle

+0

Es una peculiaridad de C, obtienes una matriz en C de 5 elementos inicializados en esa instancia de NSNumber, el molde en este caso es más una instrucción para el compilador para que conozca el tamaño de la matriz. – mxcl

Cuestiones relacionadas