2012-04-18 26 views
17

C'è un buon modo per convertire un vector<int32_t> in un NSArray di NSNumber oppure è in loop e si aggiunge a un NSMutableArray praticamente l'unico modo?convertire std: vector in NSArray

+0

NSArray non può contenere elementi del tipo primitivo NSInteger. –

+1

@ RichardJ.RossIII in realtà, * può *. ho dimostrato esattamente questo nella mia risposta. – justin

risposta

13

Se si dispone di un vettore di oggetti, è possibile effettuare le seguenti operazioni:

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

Tuttavia, se il vettore contiene i tipi primitivi, come ad esempio NSInteger, int, float, ecc, si dovrà manualmente loop i valori nel vettore e convertirli in un NSNumber prima.

+0

State molto attenti con questo approccio per quanto riguarda la durata degli oggetti del vettore! – Richard

+0

Questo risponde alla mia domanda. Ho un 'vector ' quindi sfortunatamente devo comunque scorrere tutti i valori. – mydogisbox

+1

Questo non funziona per me. Ricevo "Impossibile inizializzare un parametro di tipo 'const __unsafe_unretained id *' con un valore di tipo ..." –

5

Sì, è possibile creare un NSArray di NSInteger s da un std::vector<NSInteger> utilizzando il seguente approccio:

// 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)); 
} 

Tuttavia, sarà necessario essere molto cauti per quanto riguarda l'utilizzo di questa collezione. La Fondazione si aspetta che gli elementi siano NSObject s. Se lo passi in un'API esterna che si aspetta un array di NSObject s, probabilmente causerà un errore (leggi: EXC_BAD_ACCESS in objc_msgSend).

Di solito, uno li converte in NSNumber. Vorrei usare questo NSArray di NSInteger s nel mio programma solo se un'altra altra API era necessaria (Apple ne ha poche) - Semplicemente non giocano molto bene insieme.

+3

In realtà intendevo "NSNumber" ma +1 per una risposta affascinante! – mydogisbox