2010-10-18 4 views
5

Retour à ma question idiote quotidienne. Aujourd'hui, j'essaye de mettre une structure dans un NSArray. D'accord, c'est facile, enveloppez-le dans un NSData. Si vous me connaissez, vous savez que vous êtes sur le point de voir du code. Dans cet exemple, je charge une ligne vertex à partir d'un objet Wavefront OBJ dans une structure et je la place dans un tableau.Stockage d'une structure dans un NSArray

 NSArray *verticeLineParts = [currentLine componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; 
     Coordinate c = CoordinateMake([[verticeLineParts objectAtIndex:1] floatValue], 
             [[verticeLineParts objectAtIndex:2] floatValue], 
             [[verticeLineParts objectAtIndex:3] floatValue]); 
     [vertices addObject:[[NSData alloc] initWithBytes:&c length:sizeof(c)]]; 

Cela semble fonctionner correctement. Les premiers objets de la sortie:

2010-10-18 14:18:08.237 ObjLoader[3778:207] (
    <5d1613bd 13f3da3f 8ac745bd>, 
    <f04c28bd 13f3da3f d88048bd>, 
    <649427bd d61ddb3f d88048bd>, 
    <477625bd d845db3f d88048bd>, 
    <4c1722bd 1668db3f d88048bd>, 

Quand il vient à les imprimer après les tirant à partir du tableau, pas tant. Le code incriminé:

for (int i = 0; i < [vertices count]; i++) { 
    Coordinate c; 
    fillCoordinateFromData(c, [vertices objectAtIndex:i]); 
    NSLog(@"%@", CoordinateToNSString(c)); 
} 

[snip] 

void fillCoordinateFromData(Coordinate c, NSData *d) { 
    void *bytes = malloc(12); 
    [d getBytes:bytes]; 
    memcpy((void *)&c, &bytes, 12); 
    free(bytes); 
} 

Bien sûr, la sortie incriminée:

2010-10-18 14:22:00.692 ObjLoader[3825:207] 9.885923, -6.837428, 0.000000 
2010-10-18 14:22:00.693 ObjLoader[3825:207] 9.885923, -6.837428, 0.000000 
2010-10-18 14:22:00.694 ObjLoader[3825:207] 9.885923, -6.837428, 0.000000 
2010-10-18 14:22:00.695 ObjLoader[3825:207] 9.885923, -6.837428, 0.000000 
2010-10-18 14:22:00.695 ObjLoader[3825:207] 9.885923, -6.837428, 0.000000 

Je pense que cela est causé par C wizardry tenté par quelqu'un qui est pas sorcier C, un peu comme L'Apprenti Sorcier. Je pense que cela devrait être évident pour un sorcier du 99ème degré, ou si quelqu'un peut suggérer une façon plus moderne de le faire, faites le moi savoir.

Merci, Will

Répondre

10
void fillCoordinateFromData(Coordinate c, NSData *d) { 

Ce passe c en valeur. La modification de c dans cette fonction ne sera pas renvoyée à l'appelant.

Vous devez passer par pointeur (référence) à la place.

fillCoordinateFromData(&c, [vertices objectAtIndex:i]); 

void fillCoordinateFromData(Coordinate* pc, NSData *d) { 
    void *bytes = malloc(12); 
    [d getBytes:bytes]; 
    memcpy((void *)c, &bytes, 12); 
    free(bytes); 
} 

mais il est préférable de simplement retourner la coordonnée.

Coordinate c = getCoordinateFromData([vertices objectAtIndex:i]); 

Coordinate getCoordinateFromData(NSData* d) { 
    Coordinate c; 
    [d getBytes:&c]; // and let's not waste time allocating 12 bytes. 
    return c; 
} 

BTW, par structs convention sont enveloppées dans NSValue, non NSData.

[vertices addObject:[NSValue valueWithBytes:&c withObjCType:@encode(Coordinate)]]; 

Coordinate getCoordinateFromData(NSValue* d) { 
    Coordinate c; 
    [d getValue:&c]; 
    return c; 
}