2

我只是被困在这里,我无法弄清楚我在这里做错了什么。我对目标 c 很陌生。在我的应用程序中,我使用UITableViewandNSMutableArray来解析来自 RSS 提要的数据。当用户单击表格视图中的段控件时,我想用新数据刷新整个表格。我在表头部分添加了段控件,它可以在段索引更改时更改值。

现在的问题是,当我单击段控件时,它会在表格视图中添加新行,而不是刷新整个表格。这是代码:

- (void)addEarthquakesToList:(NSArray *)earthquakes
    {
    //NSInteger startingRow = [self.earthquakeList count];
    NSInteger earthquakeCount = [earthquakes count];
    NSMutableArray *indexPaths = [[NSMutableArray alloc] initWithCapacity:earthquakeCount];
    NSLog(@"%d",earthquakeCount);

    for (NSInteger row = 0; row < (earthquakeCount); row++)
    {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:0];
        [indexPaths addObject:indexPath];
    }

    [self.earthquakeList addObjectsFromArray:earthquakes];
    [self.tableView  insertRowsAtIndexPaths:indexPaths
                           withRowAnimation:UITableViewRowAnimationAutomatic];
}

我尝试了许多其他方法,例如[self.tableView reloadData];
我还尝试了以下方法从数组中删除所有对象并从表中删除行,但它没有显示正确的行数:

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation
{
    NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];

    for(unsigned int i = 0; i < [self.earthquakeList count]; i++)
    {
        [indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:0]];
    }

    //[self.tableView beginUpdates];
    [self.earthquakeList removeAllObjects];
    [self.tableView deleteRowsAtIndexPaths:indexPathsToDelete
                          withRowAnimation:UITableViewRowAnimationFade];
    //[self.tableView endUpdates];
    //[self.tableView reloadData];
}

这些是我的 tableView DataSource 方法:

- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section
{
    // The number of rows is equal to the number of earthquakes in the array.
    return [self.earthquakeList count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *kEarthquakeCellID = @"EarthquakeCellID";
    citsTableViewCell *cell = (citsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:kEarthquakeCellID];

    //Get the specific earthquake for this row.
    citsFuelFinder *earthquake = (self.earthquakeList)[indexPath.row];
    [cell configureWithEarthquake:earthquake];
    return cell;
}

事实上,当尝试在段控制中包含以下内容时:

- (void)segmentedControlHasChangedValue
{
    int product;
    product = fuelType.selectedSegmentIndex;

    switch (product)
    {
        case 0:
            productName=1;
            [locationManager startUpdatingLocation];
            break;

        case 1:
            productName=2;
            //[self.earthquakeList removeLastObject];
            if (![self.earthquakeList count])
            {
                [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:0]
                              withRowAnimation:UITableViewRowAnimationRight];
            }
            else
            {
                NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];
                for(unsigned int i = 0; i < [self.earthquakeList count]; i++)
                {
                    [indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i
                                                                     inSection:0]];
                }
                //[self.tableView beginUpdates];
                //[self.earthquakeList removeAllObjects];
                [self.tableView deleteRowsAtIndexPaths:indexPathsToDelete
                                      withRowAnimation:UITableViewRowAnimationFade];
                //[self.tableView endUpdates];
                [self.tableView reloadData];
                //[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
            }
            [locationManager startUpdatingLocation];
            break;

        case 2:
            productName=4;
            [locationManager startUpdatingLocation];
            break;

        case 3:
            productName=5;
            [locationManager startUpdatingLocation];
            break;

        default:
            break;
    }
}

我收到此错误:

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效更新:第 0 节中的行数无效。更新后现有节中包含的行数 (15) 必须等于该节中包含的行数更新前的节 (15),加上或减去从该节插入或删除的行数(0 插入,15 删除),加上或减去移入或移出该节的行数(0 移入,0 移动出去)。' *First throw call stack: (0x2e332e83 0x3868f6c7 0x2e332d55 0x2ecdb0af 0x30c8a34d 0x30cb083f 0x6d2d9 0x30aebda3 0x30aebd3f 0x30aebd13 0x30ad7743 0x30bf7c59 0x30bf7a27 0x30cbca25 0x30aaf1a1 0x30ae69fd 0x30ae63ab 0x30abbd79 0x30aba569 0x2e2fdf1f 0x2e2fd3e7 0x2e2fbbd7 0x2e266471 0x2e266253 0x32fa02eb 0x30b1b845 0x6948d 0x38b88ab7)

非常感谢任何帮助!

4

5 回答 5

0

试试这些替代品,稍后再给我们一些反馈(特别是如果任何 NSAssert “崩溃”了你的应用程序):

- (void)addEarthquakesToList:(NSArray *)earthquakes
{
    // data checking
    NSAssert(self.earthQuakeList != nil, @"earthQuakeList cannot be nil!");
    NSAssert(self.tableView != nil, @"tableView cannot be nil!");
    NSAssert(earthquakes != nil, @"earthquakes cannot be nil!");

    // relevant implementation
    [self.earthquakeList addObjectsFromArray:earthquakes];
    [self.tableView reloadData];
}

- (void)segmentedControlHasChangedValue
{
    // data checking
    NSAssert(self.earthQuakeList != nil, @"earthQuakeList cannot be nil!");
    NSAssert(self.tableView != nil, @"tableView cannot be nil!");
    NSAssert(fuelType != nil, @"fuelType cannot be nil!");
    NSAssert(locationManager != nil, @"locationManager cannot be nil!");

    // relevant implementation
    switch (fuelType.selectedSegmentIndex)
    {
        case 0:
            productName=1; // what is this?
            [locationManager startUpdatingLocation];
            break;

        case 1:
            productName=2;
            [self.earthquakeList removeAllObjects];
            [locationManager startUpdatingLocation];
            break;

        case 2:
            productName=4;
            [locationManager startUpdatingLocation];
            break;
        case 3:
            productName=5;
            [locationManager startUpdatingLocation];
            break;

        default:
            break;
    }

    [self.tableView reloadData]; // if you want to change the data whenever the user changes the UISegmentedControl to any new value, leave this here.
}

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation
{
    // data checking
    NSAssert(self.earthQuakeList != nil, @"earthQuakeList cannot be nil!");
    NSAssert(self.tableView != nil, @"tableView cannot be nil!");

    // relevant implementation
    [self.earthquakeList removeAllObjects];
    [self.tableView reloadData];
}
于 2014-08-15T19:30:51.030 回答
0

更新tableview的源数组,不需要插入新行。

[self.earthquakeList addObjectsFromArray:earthquakes];
[self.tableView reloadData];
于 2013-11-07T07:00:27.207 回答
0

呃,而不是

[self.tableView  insertRowsAtIndexPaths:indexPaths
                       withRowAnimation:UITableViewRowAnimationAutomatic];

尝试

[self.tableView  reloadRowsAtIndexPaths:indexPaths
                       withRowAnimation:UITableViewRowAnimationAutomatic];

无论如何....至少对我来说,您的代码片段仍然不足以找到您的问题。

但既然你说:
I want to refresh the whole table with new data when user click on the segment control in the tableview.

如果我必须制作一个带有 4 个段的分段 tableView,为不同的段显示不同的数据,我会这样做:

注意:这是一个基本示例。它不遵守您的特定代码,但应该给您一个想法,以放弃使用 indexPaths 或从数组中手动​​添加/删除对象的逻辑,而是tableView reloadData适当地使用。

- (void)viewDidLoad
{
    [super viewDidLoad];

    //declare NSArray *arrFirst, *arrSecond, *arrThird, *arrFourth, *arrSelected
    //in the .h file

    arrFirst = [[NSArray alloc] initWithObjects:@"eins",@"zwei",@"drei",@"vier",@"fünf",@"sechs", nil];
    arrSecond = [[NSArray alloc] initWithObjects:@"one",@"two",@"three",@"four",@"five",@"six",@"seven",@"eigth",@"nine", nil];
    arrThird = [[NSArray alloc] initWithObjects:@"uno",@"dos",@"tres",@"cuatro",@"cinco", nil];
    arrFourth = [[NSArray alloc] initWithObjects:@"ek",@"do",@"teen",@"chaar",@"paach",@"che",@"saat", nil];

    arrSelected = arrFirst;
}

- (IBAction)mySegmentsAct:(UISegmentedControl *)sender
{
    switch (sender.selectedSegmentIndex)
    {
        case 0:
            arrSelected = arrFirst;
            break;
        case 1:
            arrSelected = arrSecond;
            break;
        case 2:
            arrSelected = arrThird;
            break;
        case 3:
            arrSelected = arrFourth;
            break;
        default:
            arrSelected = nil;
            break;
    }

    [myTableView reloadData];
}

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

-(UITableViewCell *)tableView:(UITableView *)tableView
        cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if(cell == nil)
    {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
                                     reuseIdentifier:CellIdentifier];
    }
    cell.textLabel.text = (arrSelected)[indexPath.row];
    return cell;
}

我也可以使用单个数组来执行此操作,首先刷新旧数组内容:
arrSelected = nil
然后将新元素放入此数组(使用某些逻辑从某个来源)
,最后:
myTableView reloadData.

于 2013-11-07T09:52:25.343 回答
0

看起来当您选择了第二段并且崩溃出现了?
所以下面的代码会导致错误。

[self.tableView deleteRowsAtIndexPaths:indexPathsToDelete
                                  withRowAnimation:UITableViewRowAnimationFade];

当您使用 deleteRowsAtIndexPaths 或 insertRowAtIndexPaths 时,您必须确保数据源的长度与 tableView 的当前行匹配。

例如:您的 tableView 已经有 10 行,现在您需要删除 2 行,您应该先从数据源数组中删除 2 个数据对象,然后调用 deleteRowsAtIndexPaths。

于 2013-11-26T15:28:01.567 回答
0

如果将元素添加到数据源数组,则不会。表视图中的行数将自动更新。您不需要插入行。只需插入元素。将您的方法实现为:

- (void)addEarthquakesToList:(NSArray *)earthquakes 
{
   [self.earthquakeList addObjectsFromArray:earthquakes];
   [self.tableview reloadData];
} 
于 2013-11-07T07:09:29.690 回答