0

Hi Im trying to add an observer for my model to notify UITableview about any changes in the model. with this pattern I can decouple the model and view and I can put UITableViewDataSource in another class.

until now everything works well. but the problem is that when I inserting more than one object in the tableView the first row insert animation doesn't work.

it only happens for UITableViewRowAnimationTop. and I have tested on the real device. but no hope!

does anyone have any idea how can I fix this?

here is the code:

 - (void)viewDidLoad
{
    [super viewDidLoad];
    Item *item = [Item new];
    item.name = @"Computer";

    Item *item2 = [Item new];
    item2.name = @"lapTop";
    item2.parent = item;

    Item *item3 = [Item new];
    item3.name = @"NoteBook";
    item3.parent = item;

    item.children = [NSSet setWithObjects:item2,item3, nil];

    self.Items = [NSMutableArray arrayWithObject:item];

    [self addObserver:self
           forKeyPath:@"items"
              options:0
              context:NULL];
}

#pragma mark - Table View Data Source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.Items.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    Item *object =(Item *)[self.Items objectAtIndex: indexPath.row];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
    NSLog(@"%@",object.name);

    if (object.parent != NULL) {
        cell.indentationLevel = 1;
        cell.indentationWidth = 25;
    }
    cell.textLabel.text = object.name;
    return  cell;
}

#pragma  mark - Table View Delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSDictionary *dic=[self.Items objectAtIndex:indexPath.row];
    if([dic valueForKey:@"children"])
    {
        NSArray *children=[dic valueForKey:@"children"];
        BOOL isTableExpanded=NO;

        for(Item *child in children )
        {
            NSInteger index=[self.Items indexOfObjectIdenticalTo:child];
            isTableExpanded=(index>0 && index!=NSIntegerMax);
            if(isTableExpanded) break;
        }

        if(isTableExpanded)
        {
            [self CollapseRows:children];
        }
        else
        {
            NSUInteger count=indexPath.row+1;
            NSMutableArray *arrCells=[NSMutableArray array];
            for(Item *subItem in children )
            {
                NSLog(@"%@",subItem.name);
                if (subItem.parent != NULL) {
                    [arrCells addObject:[NSIndexPath indexPathForRow:count inSection:0]];
                    [self insertObject:subItem inItemsAtIndex:count++];
                }
            }

            //[self.tableView insertRowsAtIndexPaths:arrCells withRowAnimation:UITableViewRowAnimationTop];

        }
    }
}

-(void)CollapseRows:(NSArray*)ar
{
    for(NSDictionary *dInner in ar )
    {
        NSUInteger indexToRemove=[self.Items indexOfObjectIdenticalTo:dInner];
        NSArray *arInner=[dInner valueForKey:@"children"];
        if(arInner && [arInner count]>0)
        {
            [self CollapseRows:arInner];
        }

        if([self.Items indexOfObjectIdenticalTo:dInner]!=NSNotFound)
        {
            [self removeObjectFromItemsAtIndex:[self.Items indexOfObjectIdenticalTo:dInner]];
            //          [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:
            //                                                        [NSIndexPath indexPathForRow:indexToRemove inSection:0]
            //                                                        ]
            //                                      withRowAnimation:UITableViewRowAnimationTop];
        }
    }
}

#pragma mark KVO
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    NSIndexSet *indices = [change objectForKey:NSKeyValueChangeIndexesKey];
    if (indices == nil)
        return; // Nothing to do


    // Build index paths from index sets
    NSUInteger indexCount = [indices count];
    NSUInteger buffer[indexCount];
    [indices getIndexes:buffer maxCount:indexCount inIndexRange:nil];

    NSMutableArray *indexPathArray = [NSMutableArray array];
    for (int i = 0; i < indexCount; i++) {
        NSUInteger indexPathIndices[2];
        indexPathIndices[0] = 0;
        indexPathIndices[1] = buffer[i];
        NSIndexPath *newPath = [NSIndexPath indexPathWithIndexes:indexPathIndices length:2];
        [indexPathArray addObject:newPath];
    }

    NSNumber *kind = [change objectForKey:NSKeyValueChangeKindKey];
    if ([kind integerValue] == NSKeyValueChangeInsertion)  // Rows were added
        [self.tableView insertRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationTop];

    else if ([kind integerValue] == NSKeyValueChangeRemoval)  // Rows were removed
        [self.tableView deleteRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationTop];

}

#pragma mark Array Accessors
- (NSUInteger)countOfItems
{
    return [self.Items count];
}

- (id)objectInItemsAtIndex:(NSUInteger)idx
{
    return [self.Items objectAtIndex:idx];
}

- (void)insertObject:(id)anObject inItemsAtIndex:(NSUInteger)idx
{
    //[self willChangeValueForKey:@"menus"];
    [self.Items insertObject:anObject atIndex:idx];
}

- (void)removeObjectFromItemsAtIndex:(NSUInteger)idx
{
    [self.Items removeObjectAtIndex:idx];
}
Hashem Aboonajmi
  • 13,077
  • 8
  • 66
  • 75

1 Answers1

0

You can try to add animation directly on the first cell layer in the cellForRowAtIndexPath.

animation  = [CATransition animation];
[animation setType:kCATransitionFade];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[animation setFillMode:kCAFillModeBackwards];
[animation setDuration:.2];
[cell.view.layer addAnimation:animation forKey:@"cellAnimation"]

https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/CATransition_class/Introduction/Introduction.html

Midhun MP
  • 103,496
  • 31
  • 153
  • 200
  • oh thanks for your answer. but I don't want to hard code for special cell. if I remove KVO and uncomment the commented code it works well. but then I can't move my datasource code to another class! because theres a coupling between datasource and view controller. – Hashem Aboonajmi May 23 '14 at 18:38