Search code examples
iosobjective-cuitableviewplist

How can I delete an array from a plist using commitEditingStyle?


I have a UITableView which is populated by the array keys from a plist via this code:

-(void)viewWillAppear:(BOOL)animated
{
    // get paths from root direcory
    NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    // get documents path
    NSString *documentsPath = [paths objectAtIndex:0];
    // get the path to our Data/plist file
    NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"Data.plist"];
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithContentsOfFile:(NSString *)plistPath];
    viewerKeys = [dictionary allKeys];

    [self.tableView reloadData];
}

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

        UILabel *label = (UILabel *)[cell viewWithTag:1000];
        label.text = [viewerKeys objectAtIndex:indexPath.row];
        return cell;
}

I'm trying to enable a swipe to delete on each row in the table view, and of course this means I have to delete the row as well as the array in the plist. This is what I've tried so far:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    // get documents path
    NSString *documentsPath = [paths objectAtIndex:0];
    // get the path to our Data/plist file
    NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"Data.plist"];
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithContentsOfFile:(NSString *)plistPath];

    NSString *key = [viewerKeys objectAtIndex:indexPath.row];
    [dictionary removeObjectForKey:[NSString stringWithFormat:@"%@", key]];


    NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
    [tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
}

However it isn't writing the data back to the plist and I get this error:

Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).

This is what my plist looks like:

<plist version="1.0">
<dict>
    <key>(null)</key>
    <array>
        <string>Username</string>
        <string>Password</string>
        <string>http://www.google.com</string>
        <string>/whatever</string>
    </array>
    <key>Hello</key>
    <array>
        <string>admin</string>
        <string></string>
        <string>https://www.whatever.com</string>
        <string>/things</string>
    </array>
</dict>
</plist>

Any help would be great!


Solution

  • Your problem is you are removing that object from the dictionary only. your viewerKeys still hold removed objects key. You need to update viewerKeys before calling deleteRowsAtIndexPaths:

    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
    {
     NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    // get documents path
    NSString *documentsPath = [paths objectAtIndex:0];
    // get the path to our Data/plist file
    NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"Data.plist"];
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithContentsOfFile:(NSString *)plistPath];
    
    NSString *key = [viewerKeys objectAtIndex:indexPath.row];
    [dictionary removeObjectForKey:[NSString stringWithFormat:@"%@", key]];
    
    
     [dictionary writeToFile:plistPath atomically:YES];
     viewerKeys = [dictionary allKeys];
    
    NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
    [tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
    

    }