2016-03-08 5 views
0

Je suis nouveau avec les trucs de JSon, alors fais avec moi. Je désérialise un JSon d'une URL, et tout va bien jusqu'à ce que j'essaie de séparer les objets à l'intérieur. L'application se bloque et j'obtiens une erreur que je ne comprends pas. Peut-être que tu peux m'aider à voir ce qui me manque.Séparer des objets ou des chaînes dans NSMutableArray?

[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){ 

    if ([data length]>0 && error == nil) { 

     id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error]; 

     if (jsonObject != nil && error == nil) { 

      if ([jsonObject isKindOfClass:[NSDictionary class]]) { 

       NSDictionary *deserializedDictionary = [[NSDictionary alloc] init]; 
       deserializedDictionary = jsonObject; 
       NSLog(@"Deserialized Dictionary = %@",deserializedDictionary); 
       /* 
       LOG: Deserialized Dictionary = { d = "[{\"unit\":\"P101\",\"price\":36.0000,\"stat\":\"process\",\"type\":\"P12\"},{\"unit\":\"P102\",\"price\":38.0000,\"stat\":\"process\",\"type\":\"P13\"},..} 
       */ 

       NSMutableArray *dicts = [[NSMutableArray alloc] init]; 
       dicts = (NSMutableArray *)deserializedDictionary[@"d"]; 
       NSLog(@"Print dicts: %@",dicts); 
       /* 
       LOG: Print dicts: [{"unit":"P101","price":36.0000,"stat":"process","type":"P12"},{"unit":"P102","price":38.0000,"stat":"process","type":"P13"},..] 
       */ 

       NSLog(@"%@",NSStringFromClass([dicts class])); 
       //LOG: __NSCFString 

       NSMutableDictionary *myDict = [[NSMutableDictionary alloc] init]; 

       for (myDict in dicts) 
       { 
        NSLog(@"myDict objectForKey: id-> %@ myDict objectForKey: result-> %@",[myDict objectForKey:@"unit"],[myDict objectForKey:@"result"]); 
       } 
      } 

Et puis je reçois cette erreur:

[__NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x7fe97b327790 2016-03-08 11:29:12.946 Poop[49680:5673839] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x7fe97b327790'

Aide, s'il vous plaît?

+0

Quelque part, vous dites que votre objet est un 'NSArray' d'un' NSDictionary' (pas sûr lequel), et c'est en fait un 'NSString' qui provoque le" sélecteur non reconnu envoyé à l'instance ". Il semble que dicts class soit un 'NSString' et non un' NSMutableArray'. Et il y a somme alloc/init tout à fait faux ... – Larme

+0

Où il s'écrase exactement, sur quelle ligne?Changez aussi cette ligne - dicts = (NSMutableArray *) deserializedDictionary [@ "d"]; à dicts = dictionnaire désérialisé [@ "d"]; –

+0

Veuillez poster votre tableau échantillon afin que je puisse vérifier votre code en fonction de sa structure –

Répondre

1

partir de votre code et documentons je peux comprendre cette question réelle est de votre côté du serveur à partir de ces lignes

NSMutableArray *dicts = [[NSMutableArray alloc] init]; 
dicts = (NSMutableArray *)deserializedDictionary[@"d"]; 
NSLog(@"Print dicts: %@",dicts); 
/* 
LOG: Print dicts: [{"unit":"P101","price":36.0000,"stat":"process","type":"P12"},{"unit":"P102","price":38.0000,"stat":"process","type":"P13"},..] 
*/ 

NSLog(@"%@",NSStringFromClass([dicts class])); 
//LOG: __NSCFString 

Log dit que votre variable nommée dicts est de type NSCFString pas NSMutableArray et NSString n'ont pas les clés et Enumeration ne peut pas fonctionner sur NSString type d'objet.

Problème lié à la réponse de l'API, qui ne renvoie pas le bon JSON.

La solution consiste à modifier côté serveur pour renvoyer un tableau ou un dictionnaire au lieu d'une chaîne.

+0

s'avère, comme vous l'avez dit, ce que je recevais avait un mauvais format.J'ai essayé mon code, avec d'autres sources (api.github.com/users) et cela a marché.J'ai déjà demandé au fournisseur de service de modifier leur JSON.Merci d'avoir fait la lumière! –

0

Voir le code modifié:

[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){ 

if ([data length]>0 && error == nil) { 

    id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error]; 

    if (jsonObject != nil && error == nil) { 

     if ([jsonObject isKindOfClass:[NSDictionary class]]) { 

      NSDictionary *deserializedDictionary = [[NSDictionary alloc] init]; 
      deserializedDictionary = jsonObject; 
      NSLog(@"Deserialized Dictionary = %@",deserializedDictionary); 
      /* 
      LOG: Deserialized Dictionary = { d = "[{\"unit\":\"P101\",\"price\":36.0000,\"stat\":\"process\",\"type\":\"P12\"},{\"unit\":\"P102\",\"price\":38.0000,\"stat\":\"process\",\"type\":\"P13\"},..} 
      */ 

      NSMutableArray *responseArray = [[NSMutableArray alloc] init]; 
      responseArray = deserializedDictionary[@"d"]; 
      NSLog(@"Print responseArray: %@",responseArray); 
      /* 
      LOG: Print dicts: [{"unit":"P101","price":36.0000,"stat":"process","type":"P12"},{"unit":"P102","price":38.0000,"stat":"process","type":"P13"},..] 
      */ 

      NSLog(@"%@",NSStringFromClass([responseArray class])); 
      //LOG: __NSCFString 


      //The correct way of fast enumeration. 

      for (NSMutableDictionary *myDict in dicts) 
      { 
       NSLog(@"myDict objectForKey: id-> %@ myDict objectForKey: result-> %@",[myDict objectForKey:@"id"],[myDict objectForKey:@"result"]); 
      } 

     } 

En outre, vous devriez toujours vérifier l'existence de la clé dans le dictionnaire pour chaque fois que vous allez chercher la valeur du dictionnaire, pour cela, vous pouvez ajouter cette méthode dans votre helperClass

//Check is key exist in the dictionary 
+(BOOL)validateKeyValueForData:(id)dataValue { 

if([dataValue isEqual:[NSNull null]] || dataValue == nil) 
{ 
    return NO; 
} 

if([dataValue isKindOfClass:[NSArray class]] || [dataValue isKindOfClass:[NSMutableArray class]]) 
{ 
    if([dataValue isEqual:[NSNull null]] || dataValue == nil || [dataValue count] <= 0) 
    { 
     return NO; 
    } 
} 
else 
    if([dataValue isKindOfClass:[NSDictionary class]] || [dataValue isKindOfClass:[NSMutableDictionary class]]) 
    { 
     if([dataValue isEqual:[NSNull null]] || dataValue == nil || [dataValue count] <= 0) 
     { 
      return NO; 
     } 
    } 
    else if ([dataValue isKindOfClass:[NSString class]] || [dataValue isKindOfClass:[NSMutableString class]]) 
    { 
     if([dataValue isEqual:[NSNull null]] || dataValue == nil || [dataValue length] <= 0) 
     { 
      return NO; 
     } 
    } 

return YES; 
} 

Et utiliser comme

for (NSMutableDictionary *myDict in dicts) 
{ 

    //This way you make sure that the value for the specified key is exist in the dictionary. 
    if ([HelperClass validateKeyValueForData:myDict[@"id"]] && [HelperClass validateKeyValueForData:myDict[@"result"]]) { 

     NSLog(@"myDict objectForKey: id-> %@ myDict objectForKey: result-> %@",[myDict objectForKey:@"id"],[myDict objectForKey:@"result"]); 
    } 

}

+0

merci, j'ai fait quelques-uns des changements que vous avez suggérés et cela a fonctionné avec un autre JSON, il s'avère que celui que j'utilisais avait un mauvais format:/ –

0

Il semble que l'objet dicts soit instancié d'une manière ou d'une autre en tant que chaîne. Jetez un oeil à la NSData première, avant d'être analysé dans un objet JSON:

NSString *rawResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
NSLog(@"Raw data: %@", rawResponse); 

Si vous définissez un point d'arrêt général à prendre toutes les exceptions, il pourrait arrêter où vous essayez de parcourir votre tableau dicts. Vous pouvez le faire par:

  1. Sélectionnez le navigateur Breakpoints
  2. Cliquez sur le '+' bouton dans la partie inférieure gauche
  3. Sélectionnez 'Ajouter une exception Breakpoint ...'
  4. Dans le menu popup options, sélectionnez le Break « cAPTURE » option de