2012-04-18 16 views
17

Czy istnieje dobry sposób przekonwertować vector<int32_t> na NSArray z NSNumber lub jest w pętli i dodanie do NSMutableArray tylko w ten sposób?przekonwertować std: wektor NSArray

+0

NSArray nie może zawierać elementów typu NSInteger typu pierwotnego. –

+1

@ RichardJ.RossIII faktycznie, to * może *. Pokazałem dokładnie to w mojej odpowiedzi. – justin

Odpowiedz

13

Jeśli masz wektor obiektów, można wykonać następujące czynności:

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

Jednakże, jeśli wektor zawiera pierwotne typy, takie jak NSInteger, int, float itp, trzeba by ręcznie zapętlić wartości w wektorze i przekonwertować je najpierw na NSNumber.

+0

Zachowaj ostrożność stosując to podejście w odniesieniu do czasu życia obiektów wektorowych! – Richard

+0

To odpowiada na moje pytanie. Mam 'vector ' tak niestety muszę pętli przez wszystkie wartości w każdym razie. – mydogisbox

+1

To nie działa dla mnie. Otrzymuję komunikat "Nie można zainicjować parametru typu" const __unsafe_unretained id * "z wartością r type ..." –

5

Tak, może Załóż NSArray z NSInteger sz a std::vector<NSInteger> stosując następujące metody:

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

Jednak trzeba być bardzo ostrożnym dotyczące korzystania z tej kolekcji. Fundacja spodziewa się, że elementy będą NSObject s. Jeśli przekażesz go do zewnętrznego interfejsu API, który oczekuje tablicy NSObject s, prawdopodobnie spowoduje to błąd (przeczytaj: EXC_BAD_ACCESS w objc_msgSend).

Zazwyczaj można je przekonwertować na NSNumber. Chciałbym użyć tego NSArray z NSInteger s w moim programie tylko jeśli inny inny API potrzebował (Apple ma kilka) - Po prostu nie grają bardzo dobrze razem.

+3

Właściwie miałem na myśli 'NSNumber', ale +1 dla fascynującej odpowiedzi! – mydogisbox

Powiązane problemy