NSArrayController : removeAllObjects does not refr

2019-04-30 08:09发布

问题:

In my application I add objects directly to an ArrayController. When I want to clean all items I do:

[[downloadItemsController content] removeAllObjects];

This command however does not refresh the TableView the arraycontroller is bound to. If I remove all items and add another new items I only see that item. That is fine but if I don't add anything I still have all my items in the table.

If I do

[downloadItemsController prepareContent];

all old items are removed from the tableview but than I will get an new and empty item I can edit. I don't want that and because one of my columns has a checkboxcell I always get an row with a checkbox.

I just need an empty table with no items after I remove all existing items.

回答1:

To quickly remove all the objects from an NSArrayController object:

NSRange range = NSMakeRange(0, [[anArrayController arrangedObjects] count]);
[anArrayController removeObjectsAtArrangedObjectIndexes:[NSIndexSet indexSetWithIndexesInRange:range]];

The bindings should update automatically. See original SO answer.



回答2:

This worked for me

[anArrayController setContent:nil]

You can start populating its contents right away like this

[anArrayController addObject: @{ .... }]
[anArrayController addObject: @{ .... }.mutablecopy]
[anArrayController addObject: aDictionary]


回答3:

This is because you're modifying the controller's content "behind its back." Try using the array controller's -removeObjects: method.



回答4:

Calling removeObject.. group of methods is particularly inconvenient for a collection of Core Data objects. It seems that remove... is meant for those cases when we really need to get rid of the data (like when user press 'Remove' button at UI), so the NSArrayController will try it's best to remove objects from Core Data DB too.

I have simple manual control of NSArrayController and I found that setContent: method works great for adding, removing and replacing the array of objects inside it. And just to clear the contents setContents:@[] can be used.



回答5:

Sometimes when you remove is the key; here I defer using a volatile bool (undoInProgress) in a revert action, using solution above to flush a change array which observing method ignores while undo is in progress:

volatile bool undoInProgress = 0;
- (IBAction)revert:(id)sender
{
    NSUserDefaults * prefs = [NSUserDefaults standardUserDefaults];
    NSArray * undo = [NSArray arrayWithArray:changes];
    undoInProgress = YES;

    //  We have a single key/value pair but do so in reverse order
    for (NSInteger i=[undo count]-1; i>=0; --i)
    {
        NSDictionary * change = [undo objectAtIndex:i];
        NSString * key = [change objectForKey:@"keyPath"];
        id val = [change objectForKey:NSKeyValueChangeOldKey];

        [prefs setValue:val forKey:key];
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        NSRange range = NSMakeRange(0, [[changeController arrangedObjects] count]);
        [changeController removeObjectsAtArrangedObjectIndexes:[NSIndexSet indexSetWithIndexesInRange:range]];
        undoInProgress = NO;
    });
}