2010-01-19 6 views
2

J'ai lu beaucoup de sujets à propos de UITableViews qui ne rafraichissaient pas sur iPhone, mais je n'ai rien trouvé qui corresponde à ma situation, alors je demande de l'aide.iPhone: UITableView pas rafraichissant

Dans ma classe, qui étend UIViewController, j'ai un TableView et un 'ElementList' (qui est un wrapper pour NSMutableArray) utilisé comme source de données.

Un thread distinct ajoute un nouvel élément au tableau via la méthode 'updateList:'. Lorsque cela se produit, je veux que la tableView soit rafraîchie automatiquement, mais cela n'arrive pas. En déboguant mon application, je peux voir que 'cellForRowAtIndexPath' n'est jamais appelé et je n'arrive pas à comprendre pourquoi.

J'ai essayé d'ajouter un observateur, qui appelle la méthode 'reloadTableView' (il est réellement appelé) mais le tableau n'est pas mis à jour.

Ceci est mon code:

#import <UIKit/UIKit.h> 

@interface ListViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> 
{ 
    UITableView *tableView; 
    ElementList *elementList; // Wrapper for NSMutableArray 
} 

// Called by someone else, triggers the whole thing 
-(void)updateList:(Element *)element; 

// Added out of desperation 
-(void)reloadTableView; 

@end 


@implementation ListViewController 

-(void)loadView 
{ 
    // Create the TableView 
    tableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain]; 
    assert(tableView != nil); 
    tableView.delegate = self; 
    tableView.dataSource = self; 
    [tableView reloadData]; 

    self.view = tableView; 

    // Added out of desperation 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadTableView) name:@"UpdatedListNotification" object:nil]; 
} 

-(void)reloadTableView 
{ 
    // Try anything 
    [tableView reloadData]; 
    [tableView setNeedsLayout]; 
    [tableView setNeedsDisplay]; 
    [tableView reloadData]; 
    [self.view setNeedsLayout]; 
    [self.view setNeedsDisplay]; 
} 

// Called by someone else, triggers the whole thing 
-(void)updateList:(Element *)element 
{ 
    assert(element != nil); 
    [elementList addElement:element]; 
    [element release]; 

    // Notify the observer, which should update its table view 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"UpdatedListNotification" object:self]; 
} 

// TableView Delegate protocol 
- (void)tableView:(UITableView *)table didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    Element *selected_element = [elementList getElementAtIndex:indexPath.row]; 
    if (selected_element == nil) 
    { 
     NSLog(@"ERROR: Selected an invalid element"); 
     return; 
    } 
    [table deselectRowAtIndexPath:indexPath animated:YES]; 

    NSLog(@"Selected %@", selected_element.name); 
} 

// TableView Data Source protocol 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return [elementList count]; 
} 

- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{  
    static NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) 
    { 
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
    } 

    // Set the cell label 
    cell.textLabel.text = [[elementList getElementAtIndex:indexPath.row] name]; 
    cell.textLabel.frame = cell.bounds; 
    cell.textLabel.textAlignment = UITextAlignmentLeft; 
    return cell; 
} 

@end 

Toute aide est grandement appréciée, je vous remercie.

Répondre

13

Les notifications sont exécutées dans le même fil que l'appelant. Mise à jour de l'interface utilisateur devrait vraiment être fait dans le thread principal, vous devez donc appeler -reloadData sur le thread principal:

-(void)updateList:(Element *)element 
{ 
    assert(element != nil); 
    [elementList addElement:element]; 

    [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil]; 
} 

Notez également que vous ne devriez pas libérer un objet que vous ne possédez pas. N'appelez donc pas [release d'élément] dans votre méthode -updateList. La libération devrait être appelée par l'appelant de la fonction.

+0

Vous basculez !!! Merci :) – rippeltippel

+1

Je suis heureux d'être utile. Et pendant que vous y êtes, pensez à accepter la réponse en cliquant sur le grand 'V' sur la gauche :-) –

+0

Cela me rendait fou - merci de l'avoir signalé! – theTRON

2

Cela n'a pas fonctionné tout à fait pour moi - mais très proche. La méthode que j'ai utilisé était -

[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; 
0

Vous pouvez également faire

[self performSelectorOnMainThread:@selector(reloadTable) withObject:nil waitUntilDone:YES]; 

afin que vous puissiez mettre en œuvre une méthode sur la ViewController faire tous les trucs de l'interface utilisateur que vous avez besoin.

-(void)reloadTable 
{ 
    [self.tableView reloadData]; 
} 
Questions connexes