iPhone: UITableView не обновляется - PullRequest
2 голосов
/ 19 января 2010

Я прочитал много тем о том, что UITableView не обновляются на iPhone, но не смог найти ничего подходящего для моей ситуации, поэтому я прошу помощи.

В моем классе, который расширяет UIViewController, у меня есть TableView и ElementList (который является оберткой для NSMutableArray), используемый в качестве источника данных.

Отдельный поток добавляет новый элемент в массив с помощью метода updateList :. Когда это происходит, я хочу, чтобы tableView обновлялся автоматически, но этого не происходит.

Отладив мое приложение, я вижу, что cellForRowAtIndexPath никогда не вызывается, и я не могу понять, почему.

Я попытался добавить Observer, который вызывает метод reloadTableView (он на самом деле вызывается), но tableView не обновляется.

Это мой код:

#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

Любая помощь очень ценится, спасибо.

Ответы [ 3 ]

13 голосов
/ 19 января 2010

Уведомления выполняются в том же потоке, что и вызывающая сторона.Обновление пользовательского интерфейса действительно должно выполняться в основном потоке, поэтому вы должны вызвать -reloadData в основном потоке:

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

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

Также обратите внимание, что вы не должны освобождать объект,не владеюТак что не вызывайте [element release] в вашем методе -updateList.Релиз должен быть вызван вызывающей функцией.

2 голосов
/ 08 декабря 2013

Это не совсем сработало для меня - но очень близко. Метод, который я использовал, был -

[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
0 голосов
/ 01 сентября 2015

Вы также можете сделать

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

, чтобы вы могли реализовать метод в ViewController для выполнения всего необходимого для пользовательского интерфейса.

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