No hay una forma directa de tomar una burbuja de memoria que usted posee y "convertirla" a bajo precio en una NSArray-- después de todo, la estructura necesitaría entonces poseer esa memoria, y no sabe dónde se metió de (malloc, pila, etc.). Si hubiera un método de conveniencia para initWithArrayWrapElementsInObjects, tendría que hacer internamente lo que supones: iterar sobre la memoria proporcionada y agregar elementos a sí mismo (es posible que el framework pueda hacer esto tan rápido como memcpy, pero quién sabe).
Una forma de abordar esto (y probablemente un divertido ejercicio de aprendizaje) consiste en crear su propia subclase de NSArray que administre la memoria exactamente como desee (es decir, le permite crear e iniciar con la semántica que desee), pero que se comporta con el mundo exterior como lo haría un NSArray. Puede hacerlo heredando de NSArray e implementando los métodos count:
y objectAtIndex:
para operar en cualquier memoria que tenga. Obviamente, necesitaría implementar la administración de su propia memoria en los métodos init/dealloc, etc. Consulte esta página http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html en "Subclassing Notes".
La discusión de diseño aquí depende de cómo se vean sus datos. NSArray, por supuesto, espera que sus artículos sean referencias Obj-C (del tipo id
), y no solo fragmentos arbitrarios de datos. Si su matriz estilo C retiene estructuras u otros valores primitivos que no son referencias a objetos, entonces esta técnica no funcionará para usted: la interfaz de NSArray nunca estará contenta con elementos que no sean de referencia.
Una nota final: mencionas tomar un NSMutableArray y "crear" un NSArray con él. Debe tener en cuenta que un NSMutableArray ya es un NSArray, ya que es una subclase. Puede usar una instancia de NSMutableArray en cualquier lugar en el que desee un NSArray, sin crear una copia nueva de este.
ACTUALIZACIÓN: Faltó la nota sobre su matriz que contiene flotadores. Sí, estás un poco jodido aquí. NSArrays quiere objetos. Si la duplicación de la capacidad era la parte más costosa (como señala otro afiche), intente con initWithCapacity :. Si es el boxeo/unboxing de los flotadores en tipos de objetos, no hay nada que puedas hacer.
He creado (pero no tengo a mano) un par de clases muy simples (llamadas como MYArray y MYMutableArray) que están destinadas a envolver solo este tipo de datos con métodos similares a NSArray. Pero no son intercambiables con NSArrays. Debes usarlos intencionalmente.
ACTUALIZACIÓN # 2. Sé que han pasado años desde que esta pregunta fue en vivo, pero acabo de volver a visitarla y me di cuenta de que en este caso específico hay una forma inteligente de solucionarlo. (Desea una NSArray
no mutable de una matriz de flotador de estilo C). Puede crear una subclase personalizada de NSArray que ajuste los valores flotantes y solo los convierta en objetos cuando se acceda a ellos a través de las primitivas. Esto puede tener dificultades de rendimiento en algunas esquinas (?), Pero cumple perfectamente con sus requisitos:
@interface FloatProxyArray : NSArray
{
float * values;
NSUInteger count;
}
- (id)initWithCArray:(float *)arrayOfFloats count:(int)numberOfValues;
@end
.
@implementation FloatProxyArray
- (id)initWithCArray:(float *)arrayOfFloats count:(int)numberOfValues
{
if ((self = [super init])) {
values = (float *)malloc(numberOfValues * sizeof(float));
if (!values) {
[self release]; return nil;
}
memcpy(values, arrayOfFloats, numberOfValues * sizeof(float));
count = numberOfValues;
}
return self;
}
- (void)dealloc
{
free(values);
[super dealloc]
}
- (NSUInteger)count
{
return count;
}
- (id)objectAtIndex:(NSUInteger)index
{
if (index >= count) {
[NSException raise:NSRangeException format:@""];
return nil;
}
float val = values[index];
return [NSNumber numberWithFloat:val];
}
@end
(NB Escrito en el editor sin compilar/pruebas.)
Gracias! Eso tiene sentido. –