2012-04-18 26 views
17

¿Hay una buena forma de convertir un vector<int32_t> en un NSArray de NSNumber o está creando un bucle y agregando un NSMutableArray prácticamente de la única manera?convert std: vector to NSArray

+0

NSArray no puede contener elementos del tipo primitivo NSInteger. –

+1

@ RichardJ.RossIII en realidad, es * puede *. He demostrado exactamente esto en mi respuesta. – justin

Respuesta

13

Si usted tiene un vector de objetos, puede hacer lo siguiente:

NSArray *myArray = [NSArray arrayWithObjects:&vector[0] count:vector.size()]; 

Sin embargo, si el vector contiene los tipos primitivos, tales como NSInteger, int, float, etc., que tendría que manualmente bucle los valores en el vector y convertirlos primero a NSNumber.

+0

¡Tenga mucho cuidado con este enfoque con respecto a la vida útil de los objetos del vector! – Richard

+0

Esto responde mi pregunta. Tengo un 'vector ' así que desafortunadamente tengo que recorrer todos los valores de todos modos. – mydogisbox

+1

Esto no funciona para mí. Me aparece "No se puede inicializar un parámetro de tipo 'const __unsafe_unretained id *' con un valor de rvalue de tipo ..." –

5

Sí, se puede crear un NSArray de NSInteger s de un std::vector<NSInteger> utilizando el siguiente enfoque:

// thrown together as a quick demo. this could be improved. 
NSArray * NSIntegerVectorToNSArrayOfNSIntegers(const std::vector<NSInteger>& vec) { 

    struct MONCallback { 
    static const void* retain(CFAllocatorRef allocator, const void* value) { 
     /* nothing to do */ 
     return value; 
    } 

    static void release(CFAllocatorRef allocator, const void* value) { 
     /* nothing to do */ 
    } 

    static CFStringRef copyDescription(const void* value) { 
     const NSInteger i(*(NSInteger*)&value); 
     return CFStringCreateWithFormat(0, 0, CFSTR("MON - %d"), i); 
    } 

    static Boolean equal(const void* value1, const void* value2) { 
     const NSInteger a(*(NSInteger*)&value1); 
     const NSInteger b(*(NSInteger*)&value2); 
     return a == b; 
    } 
    }; 

    const CFArrayCallBacks callbacks = { 
    .version = 0, 
    .retain = MONCallback::retain, 
    .release = MONCallback::release, 
    .copyDescription = MONCallback::copyDescription, 
    .equal = MONCallback::equal 
    }; 

    const void** p((const void**)&vec.front()); 
    NSArray * result((NSArray*)CFArrayCreate(0, p, vec.size(), &callbacks)); 
    return [result autorelease]; 
} 

void vec_demo() { 
    static_assert(sizeof(NSInteger) == sizeof(NSInteger*), "you can only use pointer-sized values in a CFArray"); 

    std::vector<NSInteger> vec; 
    for (NSInteger i(0); i < 117; ++i) { 
    vec.push_back(i); 
    } 
    CFShow(NSIntegerVectorToNSArrayOfNSIntegers(vec)); 
} 

Sin embargo, tendrá que ser muy cautelosos con respecto a su uso de esta colección. Foundation espera que los elementos sean NSObject s. Si lo pasa a una API externa que espera una matriz de NSObject s, probablemente causará un error (léase: EXC_BAD_ACCESS en objc_msgSend).

Normalmente, uno los convertiría a NSNumber. Yo usaría este NSArray de NSInteger s en mi programa solo si otro API necesitaba (Apple tiene algunos) - Simplemente no juegan muy bien juntos.

+3

En realidad, quería decir 'NSNumber' pero +1 ¡para obtener una respuesta fascinante! – mydogisbox