表视图无/不更新

时间:2012-10-05 08:54:56

标签: objective-c ios xcode uitableview

我有一个只有一个单元格的表视图。当我调用一个方法时,我尝试刷新它,文本标签的文本应该改变。但事实并非如此,只有在视图重新出现时才会改变。

我在很多地方添加了NSLog(),并且正确的方法和条件被称为

我尝试了一些事情:

reloadData
setNeedsDisplay
setNeedsLayout
reloadCell
reloadRowsAtIndexPaths: withRowAnimation:

但是没有有效,我知道我的UITableViewDataSource代码没有问题,因为它被正确调用了。

这是我能给你的最合适的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    tableView.scrollEnabled = NO;

    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: @"cell"];

    if (cell) {

        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        if ([[TravelLogViewController locationArray] count]) {

            NSDictionary *flight = [NSDictionary dictionaryWithObjectsAndKeys:[[TravelLogViewController locationArray] lastObject], @"name", [[TravelLogViewController dateArray] lastObject], @"date", [[TravelLogViewController milesGainedIndex] lastObject], @"miles", nil];

            cell.detailTextLabel.textColor = [UIColor blackColor];

            cell.textLabel.numberOfLines = 2;
            cell.detailTextLabel.numberOfLines = 2;

            cell.textLabel.font = [UIFont fontWithName:@"Avenir" size: 14.0];
            cell.detailTextLabel.font = [UIFont fontWithName:@"Avenir" size: 12.0];

            cell.selectionStyle = UITableViewCellSelectionStyleNone;

            cell.textLabel.text = [flight objectForKey: @"name"];

            cell.detailTextLabel.text = [NSString stringWithFormat:@"Flight Date: %@, Miles Gained: %.1f", [flight objectForKey: @"date"], [[flight objectForKey: @"miles"] doubleValue]];

            cell.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1];
            //        cell.backgroundColor = [UIColor clearColor];
        }
        else {

// This gets called when I want it to, but the textLabel text or detailTextLabel text is not changed


            cell.detailTextLabel.text = nil;
            cell.textLabel.text = nil;
            cell.textLabel.font = [UIFont fontWithName:@"Arial Rounded MT Bold" size: 18.0];
            cell.textLabel.text = @"\n\n                 No Flights";
        }
    }

    return cell;
}

更新:

我正在使用ARC,并且我发现在我尝试更新单元格时表格视图为零,但我修改了我的单元格并且不知道为什么!?

我不会在任何地方发送或发布我的表视图,它仍然应该被分配

顺便说一下,我有一个标签栏控制器

更新:

我现在已经开始了赏金,一个多星期后我真的觉得这个问题需要更多的关注和答案,我已经多次检查了我的代码而我不能看看为什么表格查看没有更新/是nil

更新:

好的,我忘了提到用户可以滑动删除单元格。当他这样做时,它实际上删除单元格,它只是更改其文本(即它不更新的部分)。我将日志放入viewDidLoadviewDidAppear,并且一旦用户滑动删除,表格视图就会显示有效...这是我的代码:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

if (editingStyle == UITableViewCellEditingStyleDelete) {

    TravelLogViewController *travel = [[TravelLogViewController alloc] init];
    [travel manuallyDeleteTopCellData]; // Deletes some data in other view controller and calls the method `proceedWithDeletion`
}
}
- (void)proceedWithDeletion {

// Method is called from another view controller

NSLog(@"%@", mostRecentFlight.description); // NIL HERE

[mostRecentFlight reloadData];
[mostRecentFlight setNeedsDisplay];
[mostRecentFlight setNeedsLayout];

}

TravelLogViewController

- (void)manuallyDeleteTopCell {

[TheMileIndexViewController deductDesiredMilesToIndex: [[milesGainedIndex lastObject] floatValue]];

[locationArray removeLastObject];

[milesGainedIndex removeLastObject];

[dateArray removeLastObject];

MenuMileIndexViewController *menu = [[MenuMileIndexViewController alloc] init];
[menu proceedWithDeletion];

}

总而言之,一个视图加载/出现,表视图有效。当用户滑动删除时,它不会实际删除它只调用另一个名为TravelLogViewController方法的名为manuallyDeleteTopCellData的视图控制器,在那里删除一些数据,然后该方法调用我的原始视图控制器中的另一个方法叫proceedWithDeletion,它应该重新加载表视图,但不会(问题)。这是因为在proceedWithDeletion中,表视图为零,但为什么!?

8 个答案:

答案 0 :(得分:3)

这是一个没有任何代码的盲目镜头,但是,如果你使用dequeueReusableCellWithIdentifier,它可能会导致问题。如果您有一个单元格,则可以每次在cellForRowAtIndexPath中创建单元格,而不是重新使用已创建的单元格。用这么小的表不会影响性能

答案 1 :(得分:2)

我几乎可以确认问题不在你正在寻找或描述的领域。

我已经从头开始创建了一个示例项目,非常简单地只需要UITableViewUIButton来触发[table reloadData]并翻转一个布尔值:

BOOL toggle = NO;

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: @"cell"];

    if (cell) {

        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        if (toggle )
        {
            NSDictionary *flight = @{@"name" : @"Bob",
                                 @"date" : @"Yesterday",
                                 @"miles" : @"3" };

            cell.textLabel.text = [flight objectForKey: @"name"];
            cell.textLabel.numberOfLines = 2;

            cell.detailTextLabel.numberOfLines = 2;
            cell.detailTextLabel.textColor = [UIColor blackColor];
            cell.detailTextLabel.text = [NSString stringWithFormat:@"Flight Date: %@, Miles Gained: %.1f", [flight objectForKey: @"date"], [[flight objectForKey: @"miles"] doubleValue]];

        } else {

            cell.textLabel.text = @"blank label";
            cell.detailTextLabel.text = @"blank detail";
        }
    }
    return cell;
}

- (IBAction)toggleValue:(id)sender
{
    toggle = !toggle;
    NSLog( @"toggle is now %@", (toggle) ? @"YES" : @"NO" );

    [tv reloadData];
}

通过引用tableView:cellForRowAtIndexPath:中的布尔值并使用您提供的代码,您可以看到在调用[table reloadData]时,行实际上按预期更新。

您可以在此处下载示例项目(35KB):http://rdas.me/SampleProject.zip

我希望这能帮到你。如果没有别的,它应该可以帮助你找出事实上可能存在的地方。

祝你好运!

答案 2 :(得分:1)

manuallyDeleteTopCell的{​​{1}}实施中,此时您实例化了一个新的TravelLogViewController

MenuMileIndexViewController

这是一个不同的控制器,既没有正确初始化也没有对屏幕上的视图负责。特别是,它没有相同的MenuMileIndexViewController *menu = [[MenuMileIndexViewController alloc] init]; [menu proceedWithDeletion]; 属性。为了让mostRecentFlight调用您的原始控制器,您需要将其作为参数传递给TravelLogViewController并将其调回来,例如如下

manuallyDeleteTopCell

并按如下方式重写调用代码:

- (void)manuallyDeleteTopCell:(MenuMileIndexViewController *)origin {
    [TheMileIndexViewController deductDesiredMilesToIndex: [[milesGainedIndex lastObject] floatValue]];

    [locationArray removeLastObject];
    [milesGainedIndex removeLastObject];
    [dateArray removeLastObject];

    [origin proceedWithDeletion];
}

以前的建议:

  1. 确保在Interface Builder中正确设置了插座。你在评论中说你做到了这一点,但在另一点你说你正在使用标签栏控制器。确保在常规视图控制器(即- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { TravelLogViewController *travel = [[TravelLogViewController alloc] init]; [travel manuallyDeleteTopCellData:self]; } 的子类)上设置插座,该控制器当前可见并包含在您正在使用的UIViewController实例的viewControllers属性中。 不要继承UITabBarController (请参阅明确禁止它的Apple documentation)。的 [选中]

  2. 在调用此方法时,实施常规视图控制器的UITabBarController方法和viewDidLoad NSLog属性以验证它是非self.tableView 。的 [选中]

  3. nil的{​​{1}}中写一个@synthesize mostRecentFlight = _mostRecentFlight;语句,并在@implementation的属性上设置断点。或者,手动实现TravelLogViewController属性的@interface方法,并在此方法中设置断点。如果调用setter,将触发此断点,这将帮助您找到属性设置为setMostRecentFlight:的时间。

  4. 假设在步骤2的mostRecentFlight方法中该属性为非零,请查看对象的地址(说明的开头是{{1以nil为地址)。在代码中稍后设置要在其中使用对象的断点(当属性为nil时)。在调试器viewDidLoad处键入(使用上面的相应地址)。你得到的回应是什么?

答案 3 :(得分:1)

此代码可能是您问题的根源:

MenuMileIndexViewController *menu = [[MenuMileIndexViewController alloc] init];
[menu proceedWithDeletion];

你正在创建一个全新的MenuMileIndexViewController,而不是访问已经存在的实例,这是我认为你想要做的事情。此新实例将无法访问mostRecentFlight中存储的原始表视图。在-manuallyDeleteTopCell内,您需要引用调用MenuMileIndexViewController实例。

可能就像将self传递给-manuallyDeleteTopCellData并使用该变量随后调用-proceedWithDeletion一样简单。例如:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        TravelLogViewController *travel = [[TravelLogViewController alloc] init];
        [travel manuallyDeleteTopCellData:self];
    }
}

- (void)manuallyDeleteTopCell:(id)sender {
    [TheMileIndexViewController deductDesiredMilesToIndex: [[milesGainedIndex lastObject] floatValue]];
    [locationArray removeLastObject];
    [milesGainedIndex removeLastObject];
    [dateArray removeLastObject];
    // MenuMileIndexViewController *menu = [[MenuMileIndexViewController alloc] init];
    [sender proceedWithDeletion];
}

答案 4 :(得分:0)

我通常使用此代码:

[_myTable beginUpdates];

[... update my cell, adding / removing / changing them ...];

[_myTable endUpdates];

自5.0版以来,它适用于我的项目。

答案 5 :(得分:0)

根据您的评论,您致电tableView的{​​{1}}变量为reloadData

这种情况的常见原因是,在使用笔尖,使用ARC的弱ivars或使用同名的局部变量屏蔽ivar时,缺少指向IBOutlet的链接。

答案 6 :(得分:0)

我在代码中找不到任何错误。但是,请确保您设置了表视图数据源并委托了(应该在viewDidLoad / viewDidAppear / viewWillAppear中的某处设置):

[tableView setDelegate:self];
[tableView setDataSource:self];

在此之后,请确保从委托方法返回需要显示的行数:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return [yourDataSource count];
}
祝你好运!

答案 7 :(得分:0)

我想注意一下。如果您正在使用故事板,则无需分配您的单元格。这段代码就足够了:

- (UITableViewCell *)tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath)indexPath {

UITableViewCell *cell = [tableView 
  dequeueReusableCellWithIdentifier:@"PlayerCell"];
Player *player = [self.players objectAtIndex:indexPath.row];
cell.textLabel.text = player.name;
cell.detailTextLabel.text = player.game;
return cell;

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PlayerCell"]; Player *player = [self.players objectAtIndex:indexPath.row]; cell.textLabel.text = player.name; cell.detailTextLabel.text = player.game; return cell;