2011-03-13 6 views
0

Le code est ci-dessous:UITableView plantage lors de l'exécution délégué

@interface PreferenceViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> { 
    UITableView * preference; 
    UISegmentedControl * dimension; 
    NSArray * timeslot; 
} 

@property (nonatomic, retain) IBOutlet UITableView * preference; 
@property (nonatomic, retain) IBOutlet UISegmentedControl * dimension; 
@property (nonatomic, retain) NSArray * timeslot; 

@end 

- (void)viewDidLoad 
{ 
    preference.delegate = self; 
    preference.dataSource = self; 
    timeslot = [NSArray arrayWithObjects:@"7:00-8:00", @"8:00-9:00", @"9:00-10:00", @"10:00-11:00", @"11:00-12:00", @"12:00-13:00", @"13:00-14:00", @"14:00-15:00", @"15:00-16:00", @"16:00-17:00", nil]; 
    NSLog(@"size of array is %d", [timeslot count]); 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view from its nib. 
} 

- (void)viewDidUnload 
{ 
    [super viewDidUnload]; 
    // Release any retained subviews of the main view. 
    // e.g. self.myOutlet = nil; 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    // Return YES for supported orientations 
    return (interfaceOrientation == UIInterfaceOrientationPortrait); 
} 

#pragma mark - Table View delegate 
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 

} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    if (dimension.selectedSegmentIndex == 0){ 
     return [timeslot count]; 
    }else 
     return 15; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    //NSLog(@"TESTING"); 
    static NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease]; 
    } 
    // this is the MAGIC line! 

    if (dimension.selectedSegmentIndex == 0) 
     cell.text = [timeslot objectAtIndex:indexPath.row]; 

    return cell; 
} 

Je me demandais ce qui cause l'accident? Il arrive dans ce délégué numberOfRowsInSection et l'appel à compter les intervalles de temps ..

Répondre

1
timeslot = [NSArray arrayWithObjects:@"7:00-8:00", @"8:00-9:00", @"9:00-10:00", @"10:00-11:00", @"11:00-12:00", @"12:00-13:00", @"13:00-14:00", @"14:00-15:00", @"15:00-16:00", @"16:00-17:00", nil]; 

Cette ligne devrait avoir -retain.

timeslot = [[NSArray arrayWithObjects:@"7:00-8:00", @"8:00-9:00", @"9:00-10:00", @"10:00-11:00", @"11:00-12:00", @"12:00-13:00", @"13:00-14:00", @"14:00-15:00", @"15:00-16:00", @"16:00-17:00", nil] retain]; 

UPD -autorelease est pas une bonne idée. Vous pouvez uniquement libérer/libérer les objets que vous possédez. Lorsque vous avez utilisé -arrayWithObjects votre objet appartient à la société locale AutoreleasePool.

Voici comment cela fonctionne en termes simples. Chaque fois que vous créez un objet sans-alloc ou -copy les méthodes sont auto-libérées, ce qui signifie qu'il aura le nombre de références 1 jusqu'à la fin de la portée du message. Techically autorelease pool business est asynchrone, donc il peut tomber en panne ou ne peut pas, mais vous devez supposer que cet objet est zombie à ce stade. Vous devez donc utiliser -retain afin de préserver cet objet pour l'utilisation d'une autre méthode. Si vous avez utilisé explicitement -retain, vous devez utiliser -release explicitement lorsque vous avez terminé avec cet objet. Alors pourquoi ne pas utiliser [[NSArray alloc] initWithObjects:...] tout de suite. c'est juste plus approprié ici. Vous pouvez également utiliser la propriété conservée, mais vous ne voulez pas exposer les variables internes lorsque vous n'en avez pas.

+1

Cela ne ferait qu'aggraver le problème. Le tableau renvoyé par '[NSArray arrayWithObjects: ...]' n'appartient pas à vous, donc autoreleasing le ferait éventuellement être relâché trop de fois. – Anomie

+0

@Anomie Je comprends très bien le processus sous-jacent. Tu n'as pas besoin de m'apprendre. A propos de "ça le ferait éventuellement sortir trop de fois" c'est vraiment marrant. – bioffe

+0

Alors pourquoi avez-vous posté un commentaire aussi flagrant? – Anomie

0

En viewDidLoad, vous assignez nouvellement créé (et autoreleased) NSArray au Ivar plutôt que la propriété, ce qui signifie qu'il est pas retenu pour vous. Ainsi, au moment où il arrive à tableView:numberOfRowsInSection: la matrice a été éliminée et vous obtenez EXC_BAD_ACCESS ou un crash similaire.

Pour cette raison, je nomme habituellement mes ivars _name plutôt que name pour correspondre à la propriété. Cela signifie que la ligne de synthèse doit être la plus compliquée @synthesize name=_name, mais elle empêche l'assignation accidentelle à l'ivar plutôt qu'à la propriété.

+0

vous dites que je devrais changer @synthesize timelot à @synthesize timeslot = _timeslot; ? comme je l'ai essayé aussi et ça n'a pas marché – aherlambang

+0

@EquinoX ne l'écoute pas. Vous auriez besoin d'une propriété conservée ici. Changez simplement 'arrayWithObjects' en' initWithObjects' et relâchez votre objet alloué une fois que vous avez terminé. – bioffe

+0

@bioffe merci mec .. mais l'esprit expliquant avec arrayWithObjects ne fonctionne pas? – aherlambang

Questions connexes