2010-03-02 4 views
4

Je consomme un service Web dans mon application iPhone. La méthode de service Web renvoie une réponse qui comporte plusieurs champs (par exemple, ID, description, etc.). Un de ces champs contient des données d'image binaires que j'ai besoin de convertir en UIImage dans mon application iPhone. J'utilise avec succès un NSXMLParser pour extraire des données de la réponse XML. Dans le sélecteur parser:foundCharacters: du XMLParser, un NSString* pointe vers la chaîne dans chaque champ. Comme il est une chaîne, ce que je fais pour lire des données d'image quand je rencontre le champ d'image:Lecture de données d'image binaire à partir d'un service Web dans UIImage

UIImage *img = [[UIImage alloc] initWithData:[string dataUsingEncoding:NSUTF8StringEncoding]]; 

, mais la variable img est encore « néant » après cette ligne. On dirait que les données de la chaîne XML ne sont pas compatibles avec la conversion. Qu'est-ce que je fais mal ici? (Je suis capable de lire d'autres champs dans mes variables, mais pas ce champ de données d'image)

Merci d'avance ..

Répondre

5

Après la réponse de fbrereto, j'ai réussi à convertir la chaîne en NSData en utilisant un exemple de code à ce lien: http://www.cocoadev.com/index.pl?BaseSixtyFour (faites défiler jusqu'à l'échantillon de code par l'utilisateur MiloBird). Maintenant, je peux construire l'image avec succès.

Il utilise les catégories d'objectif-c pour ajouter le sélecteur + (id)dataWithBase64EncodedString:(NSString *)string; à la classe NSData. Voici l'exemple de code nécessaire que j'ai extrait du lien ci-dessus:

//MBBase64.h 

@interface NSData (MBBase64) 

+ (id)dataWithBase64EncodedString:(NSString *)string;  // Padding '=' characters are optional. Whitespace is ignored. 

@end 


//MBBase64.m 

static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/"; 

@implementation NSData (MBBase64) 

+ (id)dataWithBase64EncodedString:(NSString *)string; 
{ 
    if (string == nil) 
     [NSException raise:NSInvalidArgumentException format:nil]; 
    if ([string length] == 0) 
     return [NSData data]; 

    static char *decodingTable = NULL; 
    if (decodingTable == NULL) 
    { 
     decodingTable = malloc(256); 
     if (decodingTable == NULL) 
      return nil; 
     memset(decodingTable, CHAR_MAX, 256); 
     NSUInteger i; 
     for (i = 0; i < 64; i++) 
      decodingTable[(short)encodingTable[i]] = i; 
    } 

    const char *characters = [string cStringUsingEncoding:NSASCIIStringEncoding]; 
    if (characters == NULL)  // Not an ASCII string! 
     return nil; 
    char *bytes = malloc((([string length] + 3)/4) * 3); 
    if (bytes == NULL) 
     return nil; 
    NSUInteger length = 0; 

    NSUInteger i = 0; 
    while (YES) 
    { 
     char buffer[4]; 
     short bufferLength; 
     for (bufferLength = 0; bufferLength < 4; i++) 
     { 
      if (characters[i] == '\0') 
       break; 
      if (isspace(characters[i]) || characters[i] == '=') 
       continue; 
      buffer[bufferLength] = decodingTable[(short)characters[i]]; 
      if (buffer[bufferLength++] == CHAR_MAX)  // Illegal character! 
      { 
       free(bytes); 
       return nil; 
      } 
     } 

     if (bufferLength == 0) 
      break; 
     if (bufferLength == 1)  // At least two characters are needed to produce one byte! 
     { 
      free(bytes); 
      return nil; 
     } 

     // Decode the characters in the buffer to bytes. 
     bytes[length++] = (buffer[0] << 2) | (buffer[1] >> 4); 
     if (bufferLength > 2) 
      bytes[length++] = (buffer[1] << 4) | (buffer[2] >> 2); 
     if (bufferLength > 3) 
      bytes[length++] = (buffer[2] << 6) | buffer[3]; 
    } 

    realloc(bytes, length); 
    return [NSData dataWithBytesNoCopy:bytes length:length]; 
} 

@end 

Merci à tous!

+0

J'ai le problème exact comme vous l'avez fait. Je suis heureux d'avoir trouvé votre réponse, mais je ne comprends pas vraiment le code et comment l'utiliser. J'ai une chaîne currentElementValue que j'ai analysée d'un service Web et je veux convertir ceci en nsdata, de sorte que je puisse convertir plus loin en image. Pourriez-vous me donner quelques suggestions s'il vous plaît? Je vous remercie. – alin

+1

Peut-être qu'il est très tard pour cette réponse. Mais vous pouvez utiliser la méthode fournie dans l'exemple et l'appeler comme ceci: NSData * data = [NSData dataWithBase64EncodedString: currentElementValue]; UIImage * img = [UIImage imageWithData: données]; – ravinsp

1

Le truc avec NSString est qu'il ya un codage implicite associé aux données qu'il contient. L'image que vous recevez, cependant, est probablement dans un format qui ne convertira pas correctement, car il s'agit de données binaires ou d'un codage sans perte de données binaires (par exemple, base64). L'astuce consiste donc à s'assurer que vous n'effectuez aucune conversion d'encodage, sinon vos données d'image seront corrompues. Au lieu d'utiliser dataUsingEncoding: je voudrais essayer une API plus comme getBytes:maxLength:usedLength:encoding:options:range:remainingRange. Bien que plus complexe que dataUsingEncoding: je pense que cela vous donnera la flexibilité dont vous avez besoin pour obtenir juste les données de la NSString et rien de plus.

+0

Merci pour votre idée précieuse, mais encore une fois, je devrais connaître le nombre d'octets dans la chaîne. Comment puis-je savoir ça? '' [longueur de la chaîne] 'et' [chaîne lengthOfBytesUsingEncoding] 'implique à la fois un encodage de caractères. Si je peux connaître la longueur des octets, je pourrais utiliser [string getCString] pour obtenir les octets bruts. Merci encore. – ravinsp