【问题标题】:Updating NSMutableArray from sectioned tableview after item is deleted删除项目后从分段表视图更新 NSMutableArray
【发布时间】:2012-07-06 20:01:43
【问题描述】:

我有一个按字母顺序划分的表格视图。我有一个NSMutableArray *drinks,这是我的原始数据源,其中填充了来自 plist 的NSMutableDictionary's。在我的viewDidLoad 方法中。然后,我遍历我的数组并在我的 viewWillAppear 方法中创建部分的键和每个部分中的行数

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.sections = [[NSMutableDictionary alloc] init];
    BOOL found;

    // Loop through the whiskys and create our keys
    for (NSMutableDictionary *whisky in self.drinks)
    {
        NSString *c = [[whisky objectForKey:NAME_KEY] substringToIndex:1];

        found = NO;

        for (NSString *str in [self.sections allKeys])
        {
            if ([str isEqualToString:c])
            {
                found = YES;
            }
        }

        if (!found)
        {
            [self.sections setValue:[[NSMutableArray alloc] init] forKey:c];
        }
    }
    // Loop again and sort the whiskys into their respective keys
    for (NSDictionary *whisky in self.drinks)
    {
        [[self.sections objectForKey:[[whisky objectForKey:NAME_KEY] substringToIndex:1]] addObject:whisky];
    }
    // Sort each section array
    for (NSString *key in [self.sections allKeys])
    {
        [[self.sections objectForKey:key] sortUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:NAME_KEY ascending:YES]]];
    }
        [self.tableView reloadData];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view

    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [searchPaths lastObject];
    NSString *writeableDBPath = [documentsDirectory stringByAppendingPathComponent:@"ScotchList.plist"];

    NSMutableArray *tmpArray = [[NSMutableArray alloc]initWithContentsOfFile:writeableDBPath];

    self.drinks = tmpArray;

    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(applicationDidEnterBackground:) 
                                                 name:UIApplicationDidEnterBackgroundNotification
                                               object:nil];

    //Register for application exiting information so we can save data
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];

}

所有这些都很好用。然后,当我删除一行时,它也可以正常工作。但是,当我转到新视图并返回 tableview 时,已删除的行会重新出现。所以我需要更新我的原始数据源(饮料),因为每次 viewAppears 它都会再次从原始数据源中提取。所以我试图在行中获取项目(威士忌)并将其从数组中删除。但它会抛出一个 sigabrt。这是我的删除行方法。

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        //DELETE THE ROW FROM THE DATA SOURCE
        [self.tableView beginUpdates];

        [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] removeObjectAtIndex:indexPath.row];

        NSDictionary *whisky = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
        [self.drinks removeObject:whisky];

        if ([[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] count] > 0)
        {
            // Section is not yet empty, so delete only the current row.
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

        }
        else
        {
            // Section is now completely empty, so delete the entire section.
            [self.sections removeObjectForKey:[[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]];
            [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section]
                     withRowAnimation:UITableViewRowAnimationFade];
        }

        [self.tableView endUpdates];
    } else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
    }
}

这是日志显示的内容:

2012-07-06 15:36:42.454 WhiskyBook[3275:907] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'

*** First throw call stack:

(0x3998a17b 0x3494395b 0x398d83bd 0x3e6b5 0x32a0cd11 0x328f0d09 0x328f0cbb 0x328f0c95 0x328f09eb 0x328f1369 0x328ef791 0x328dd72d 0x328dd009 0x339a7603 0x339a7233 0x3995a873 0x3995a817 0x39959611 0x398d6be5 0x398d6a71 0x339a634b 0x329037f5 0x3ac09 0x33cc7b20)

libc++abi.dylib: terminate called throwing an exception

(lldb) 

我做错了什么?

【问题讨论】:

  • 这是在哪一行调用的?您可以通过输出您正在查看的数组并查看哪个为 nil 来解决此问题。
  • 此外,您似乎正在尝试更改不可变数组 - 这就是您的错误包含 __NSArrayI 的原因(I 代表不可变)
  • 当我在“tableview commitEditingStyle”方法中放入“NSDictionary *whisky”时,问题就出现了。当我将威士忌输出到日志时,它会以应有的方式显示项目(威士忌)。
  • 我找到了解决问题的方法。我没有尝试从 commitEditingStyle 方法内的原始数据源中删除对象,而是为我的 master-viewController 分配了一个 NSDictionary 属性,并在我的 viewDidLoad 中对其进行了初始化,然后为其分配了我想要在其中删除的项目commitEditingStyle 方法。然后在我的 viewWillDisappear 方法中,我将它从原始数据源中删除。

标签: objective-c ios5 uitableview


【解决方案1】:

我找到了解决问题的方法。我没有尝试从 commitEditingStyle 方法内的原始数据源中删除对象,而是为我的 master-viewController 分配了一个 NSDictionary 属性,并在我的 viewDidLoad 中对其进行了初始化,然后为其分配了我想要在其中删除的项目commitEditingStyle 方法。然后在我的 viewWillDisappear 方法中,我将它从原始数据源中删除。

【讨论】:

    猜你喜欢
    • 2019-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-26
    • 2015-01-04
    • 1970-01-01
    相关资源
    最近更新 更多