2011-10-04 2 views
1

Construire un UIPickerView personnalisé pour que je puisse laisser mes utilisateurs sélectionner l'heure comme 24 heures sans avoir à aller dans l'application Paramètres et activer 24 heures pour l'ensemble du téléphone. J'ai quelques fuites tenaces d'un couple de cordes et d'un tableau, et je pourrais vraiment utiliser de l'aide.Fuites étranges dans les méthodes UIPickerView

Il n'y a que trois endroits où les tableaux que je crée avec les chaînes sont utilisés. heures et minutes sont à la fois NSArray propriétés synthétisées ainsi que les ivars.

a) Dans viewWillAppear: animé, où les chaînes et les tableaux sont effectivement créés:

if (TwentyFourHourMode) { 
    //set up arrays for 24 hour picker 

    NSMutableArray *hoursMutable = [[NSMutableArray alloc] init]; 
    NSString *hourString; 
    for (int i = 0; i < 24; i++) { 
     if (i < 10) { 
      hourString = [NSString stringWithFormat:@"0%i", i]; 
     } else { 
      hourString = [NSString stringWithFormat:@"%i", i]; 
     } 
     [hoursMutable addObject:hourString]; 
    } 
    self.hours = [[NSArray alloc] initWithArray:hoursMutable]; 
    [hoursMutable release]; 

    NSMutableArray *minutesMutable = [[NSMutableArray alloc] init]; 
    NSString *minuteString; 
    for (int i = 0; i < 60; i++) { 
     if (i < 10) { 
      minuteString = [NSString stringWithFormat:@"0%i", i]; 
     } else { 
      minuteString= [NSString stringWithFormat:@"%i", i]; 
     } 
     [minutesMutable addObject:minuteString]; 
    } 
    self.minutes = [[NSArray alloc] initWithArray:minutesMutable]; 
    [minutesMutable release]; 
    //more stuff which does not leak or reference the arrays/strings in question 
} else { 
    //unrelated crap 
} 

b) dans mes méthodes de délégués de UIPickerView - tout ce qui utilise ces deux tableaux:

-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 
    return 2; 
} 

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 
    if (component == 0) { 
     return self.hours.count; 
    } else if (component == 1) { 
     return self.minutes.count; 
    } else { 
     return 0; 
    }  
} 

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component 
{ 
    if (component == 0) { 
     return [self.hours objectAtIndex:row]; 
    } else if (component == 1) { 
     return [self.minutes objectAtIndex:row]; 
    } else { 
     return nil; 
    } 
} 

- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component { 
    switch(component) { 
     case 0: return 44; 
     case 1: return 50; 
     default: return 44; 
    } 

} 

- (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component 
{ 
    if (component == 0) { 
     [hour24 release]; 
     hour24 = [self.hours objectAtIndex:row]; 
     [hour24 retain]; 
    } else if (component == 1) { 
     [minute24 release]; 
     minute24 = [self.minutes objectAtIndex:row]; 
     [minute24 retain]; 
    } 

c) et last but not least, dans dealloc:

//set arrays to nil 
self.hours = nil; 
self.minutes = nil; 

//release arrays 
[hours release]; 
[minutes release]; 

Analyze est PROCHAINEMENT propre, mais struments me dit que hourString, minuteString et self.hours sont tous fuites. Ce qui me rend vraiment fou, c'est que self.minutes ne fuit pas et il semble que ce soit le même format de code que self.hours - j'ai même copié-collé et j'ai toujours la même fuite/aucune combinaison de fuite. Je serai damné si je peux comprendre d'où cela vient. Des idées? Tout autre code que vous pourriez avoir besoin d'aide? Merci les gars!

Modifier: suggestion de EmptyStack arrêté self.hours et minuteString d'être une fuite, mais hourString est toujours une fuite et il y a maintenant une nouvelle fuite dans ce code juste en dessous de la substance ci-dessus dans viewWillAppear:animated (self.incomingTime est une synthèse NSString propriété, tous les tableaux ici sont initialisées localement):

NSArray *splitStrings = [self.incomingTime componentsSeparatedByString:@":"]; 
NSString *hourToDisplay = [splitStrings objectAtIndex:0]; 
//set this here so it doesn't give a null value 
hour24 = [[NSString alloc] initWithString:hourToDisplay]; 
NSString *minuteSplitter = [splitStrings objectAtIndex:1]; 
NSArray *splitMinutes = [minuteSplitter componentsSeparatedByString:@" "]; 
NSString *minuteToDisplay = [splitMinutes objectAtIndex:0]; 
minute24 = [[NSString alloc] initWithString:minuteToDisplay]; 

Edit 2: Oh, pour pleurer à haute voix, maintenant minuteString coule à nouveau. Je vais me coucher avant que ma tête n'explose. Toute suggestion du jour au lendemain serait la bienvenue.

Répondre

2

Les problèmes sont dans les lignes suivantes,

self.hours = [[NSArray alloc] initWithArray:hoursMutable]; 
self.minutes = [[NSArray alloc] initWithArray:minutesMutable]; 

Il semble heures et minutes sont « propriétés » retenues et vous attribuez des objets tout en lui attribuant aux propriétés. Par exemple sur la première ligne, [NSArray alloc] augmente le retainCount par 1 et le setter self.hours augmente à son tour le retainCount par 1. Enfin, le retainCount devient 2, ce qui provoque la fuite même après la libération de ces objets. Vous pouvez utiliser des constructeurs de commodité dans ces cas.

self.hours = [NSArray arrayWithArray:hoursMutable]; 
self.minutes = [NSArray arrayWithArray:minutesMutable]; 

Et même une façon plus simple est d'attribuer directement ces tableaux comme celui-ci enfin,

self.hours = hoursMutable; 
self.minutes = minutesMutable; 
+0

Eh bien, cela a aidé - self.hours et minuteString ne sont plus divulgués. Cependant, hourString est toujours en train de fuir et il y a maintenant une nouvelle fuite de ce tableau: 'NSArray * splitStrings = [self.incomingTime componentsSeparatedByString: @": "];' – DesignatedNerd

1

D'accord, trouvé ce, pour tous ceux qui en trébuchant dans à l'avenir: hour24 et minute24 n'étaient pas correctement sorti en dealloc, donc ça fuyait les ficelles et les réseaux partout. Je l'ai trouvé en commentant le code affiché dans la deuxième édition et en le remettant en ligne par ligne jusqu'à ce que la fuite se produise. Merci pour les suggestions!

Questions connexes