2010-10-29 3 views
0

J'ai récemment créé une nouvelle classe pour mon application iPhone qui va contenir des informations lues à partir d'un fichier texte contenant l'adresse postale et les points GPS des points d'intérêt. Le problème est cependant que chaque fois que j'ajoute du code pour initialiser la classe, mon application se charge et s'arrête instantanément sans erreur dans la console. Quand je l'enlève, tout va bien. Je ne peux tout simplement pas voir quelque chose de mal avec le code.Application de rupture d'initialisation de classe

Voici le constructeur:

#import "GPSCoordinate.h" 


@implementation GPSCoordinate 
-(GPSCoordinate*) initWithData:(NSString *)rawData size:(int)size 
{ 
self = [super init]; 
location = [NSMutableArray arrayWithCapacity:size]; 
coordinates = [NSMutableArray arrayWithCapacity:(int)size]; 

NSArray *tokens = [rawData componentsSeparatedByString:@"@"]; 

for (int i = 0; i < size - 1; i++) { 
    //Sub tokens 
    NSString *line = [tokens objectAtIndex:i]; 
    NSArray *lineTokens = [line componentsSeparatedByString:@":"]; 
    //Store address 
    [location addObject:[lineTokens objectAtIndex:0]]; 
    //Store GPS coords 
    NSString *coords = [lineTokens objectAtIndex:1]; 
    coords = [[coords stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:@""] 
       stringByReplacingCharactersInRange:NSMakeRange([coords length]-2, 1) withString:@""]; 
    NSArray *coordsTokens = [coords componentsSeparatedByString:@" "]; 
    CLLocationCoordinate2D coord; 
    coord.latitude = [[coordsTokens objectAtIndex:0] doubleValue]; 
    coord.longitude =[[coordsTokens objectAtIndex:1] doubleValue]; 
    [coordinates addObject:coords]; 
    [line release]; 
    [lineTokens release]; 
    [coords release]; 
    [coordsTokens release]; 
} 

return self; 
} 

@end 

Voici l'appel que je fais à dans une autre classe:

self.gps = [[GPSCoordinate alloc] initWithData:gpsRawData size:[[gpsRawData componentsSeparatedByString:@"@"] count]]; 

Où vais-je pas avec cela?

+0

Y a-t-il un message d'erreur sur la console? – taskinoor

+0

il n'y a aucune vérification d'erreur sur l'un des paramètres, je voudrais commencer là. –

+0

Avez-vous un point de rupture ici? Pourrait vous amener à la ligne individuelle. Vous pouvez obtenir des informations sur les objets à la console en tapant 'po ' –

Répondre

6

Je vois un certain nombre de problèmes.

  • Vous ne vérifiez pas la valeur de retour de [super init].
  • Vous stockez des tableaux auto-libérés dans ce qui sont probablement des ivars (emplacement et coordonnées).
  • Vous passez un paramètre de taille séparé qui est calculé à partir de la rawData en dehors de l'appel, mais -initWithData: effectue exactement le même calcul dans la méthode. La taille: paramètre semble complètement superflu ici.
  • Vous ignorez entièrement le dernier jeton. Vous devriez prendre cela pour la boucle et rendre la condition simplement i < size. Alternativement si vous iOS 4.0 ou ciblage ci-dessus, vous pouvez transformer la boucle entière en

    [tokens enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){ 
        NSString *line = obj; 
        // rest of loop body 
    }]; 
    

    Puisque vous ne semblez pas avoir besoin de l'index dans la boucle, vous pouvez aussi utiliser une boucle for-in (ce fonctionnera sur les appareils iOS 4.0 pré):

    for (NSString *line in tokens) { 
        // body of loop 
    } 
    
  • Vous ne vérifiez pas que vos données sont en cours de validité. Si une ligne contient "foo", votre programme va planter quand il essayera d'accéder à [lineTokens objectAtIndex:1]. De même, il se bloque si vous avez la chaîne "foo:" alors qu'il essaie de supprimer le premier caractère de la variable coordinates. En fait, tout ce qui est inférieur à 2 caractères après le colon va planter. Il va aussi planter s'il n'y a pas d'espace après le deux-points.

  • Et enfin, tous ces appels à -release à la fin se bloqueront. Les quatre objets sont des objets auto-libérés, donc en appelant -release sur eux maintenant vous garantissez simplement que l'application va planter lorsque le pool autorelease est drainé.
  • Vous stockez également coords (par exemple, la chaîne) dans votre tableau coordinates. Vraisemblablement, vous vouliez stocker coord, bien que vous deviez l'envelopper dans un NSValue afin de le stocker dans un NSArray.
+0

+1 pour la suggestion de for-in; Je pense que cela aiderait beaucoup ce code –

2

Je vois plusieurs problèmes.

1) Plus fondamentalement, vous libérez beaucoup d'objets que vous n'avez pas alloués. Par exemple:

NSString *line = [tokens objectAtIndex:i]; 
.... 
[line release]; 

est incorrect. Passez en revue le Cocoa Memory Management Rules.

2) Pourquoi faites-vous [[gpsRawData componentsSeparatedByString:@"@"] count pour passer la taille de votre méthode initWithData:size:, quand vous allez juste devoir répéter l'appel -componentsSeparatedByString: dans votre méthode. Passer une "taille" séparée ne vous rapporte rien, implique une analyse redondante de l'entrée, et ouvre plus de bogues possibles (si l'appelant passe une "taille" qui ne correspond pas au nombre de "@" dans l'entrée - vous ne gérez pas cette condition d'erreur).

3) Je vois également que vous assignez la latitude/longitude à CLLocationCoordinate2D coord; mais que vous ne faites rien avec. Est-ce délibéré?