2

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

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,并且在尝试更新单元格时发现表格视图为零,但是我已经修改了单元格并且不知道为什么!

我没有在任何地方取消或释放我的表格视图,它仍然应该被分配

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

更新:

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

更新:

好的,我忘了提到用户可以滑动删除单元格。当他这样做时,它实际上并没有删除单元格,它只是更改了它的文本(即它没有更新的部分)。一旦用户滑动删除,我输入日志viewDidLoad并且viewDidAppear表格视图似乎是有效的......这是我的代码:

- (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它应该重新加载表视图的位置,但没有(问题)。这样做的原因是因为在proceedWithDeletiontable view 中是 nil,但是为什么呢!?

4

8 回答 8

3

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

于 2012-10-05T09:08:48.610 回答
2

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

我从头开始创建了一个示例项目,只需放置一个UITableView触发UIButtona[table reloadData]并翻转布尔值的 a 和 a :

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

我希望这对你有帮助。如果没有别的,它应该可以帮助您隔离问题实际上可能存在的位置。

祝你好运!

于 2012-10-15T20:43:14.117 回答
1

在您的实现中manuallyDeleteTopCell,此时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];
}

并将调用代码改写如下:

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

以前的建议:

  1. 确保您已在 Interface Builder 中正确设置了插座。您在评论中说您这样做了,但在另一点您说您正在使用标签栏控制器。确保您在常规视图控制器(即 的子类UIViewController)上设置插座,该控制器当前可见并包含在您正在使用的实例的viewControllers属性中。不要子类化(请参阅明确禁止它的Apple 文档)。[检查]UITabBarControllerUITabBarController

  2. 在调用此方法时,实现viewDidLoad常规视图控制器的方法和NSLog属性self.tableView以验证它是否为非nil[检查]

  3. 在of中写一条@synthesize mostRecentFlight = _mostRecentFlight;语句,并在. 或者,手动实现属性的方法并在此方法内设置断点。如果调用 setter 会触发此断点,这将帮助您找到属性设置为的时间。@implementationTravelLogViewController@interfacesetMostRecentFlight:mostRecentFlightnil

  4. 假设在步骤 2 的方法中属性不是 nil viewDidLoad,请查看对象的地址(描述的开头表示(UITableView *) $1 = 0xXXXXXXXX0xXXXXXXXX地址)。稍后在代码中(当属性为 nil 时)设置要在其中使用对象的断点。在调试器中键入po 0xXXXXXXXX(使用上面的适当地址)。你得到什么回应?

于 2012-10-15T19:55:18.637 回答
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];
}
于 2012-10-16T05:48:02.590 回答
0

我通常使用以下代码:

[_myTable beginUpdates];

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

[_myTable endUpdates];

从 5.0 版开始,它适用于我的项目。

于 2012-10-05T09:03:08.447 回答
0

根据您的评论,tableView您调用的变量reloadDatanil.

造成这种情况的常见原因是在使用 nib 的情况下缺少指向 IBOutlet 的链接、带有 ARC 的弱 ivar 或使用同名的局部变量屏蔽 ivar。

于 2012-10-05T13:05:42.523 回答
0

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

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

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

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

    return [yourDataSource count];
}

祝你好运!

于 2012-10-12T16:53:24.307 回答
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;

}

于 2012-10-16T05:06:57.727 回答