0

I want to insert UIViews dynamically with animation, based on incoming Data.

I send two asynchronous URLRequests and get the received data back from another thread.

I'm observing a property, which gets dynamically filled with data from different Requests. So KVO sends me messages, probably directly after each other.

With the first incoming message, I start a few dependent animations. During the animation time it often occurs, that new data arrives and messages my observer. I then want to wait until the animations are over and start the animations for the new data.

I'm looking for a nice implementation, not something with a while loop, waiting until a bool changes.

EDIT: Consider that I cannot say, which data comes in first. So I cannot define a animation method as the first one.

Fab1n
  • 2,103
  • 18
  • 32

4 Answers4

2

How about adding the incoming views to a mutableArray as they come in and then use something like this:

-(void) animateView:(UIView *)viewToAnimate{    

    [UIView animateWithDuration:0.5 animations:^{
        viewToAnimate.alpha = 0;
    }
                 completion:^(BOOL finished){
                     [_mutableArrayOfAnimationViews removeObject: viewToAnimate];
                     if ([_mutableArrayOfAnimationViews count] > 0) {
                         UIView *newAnimationView = [_mutableArrayOfAnimationViews objectAtIndex:0];
                         [self animateView: newAnimationView];
                     }
                 }];   
}

Then you can also check when the views come in whether the array is already empty, and if so call the above method...

T. Benjamin Larsen
  • 6,373
  • 4
  • 22
  • 32
  • 1
    +1 agree. didn't see this load as i was typing essentially the same idea. though, i think it's better to performSelector then just call recursively. – danh Jan 31 '13 at 18:06
2

How about create a mutable array that's your kvoToDoList for animations. Put whatever info in there you need to launch the animation (like the object that got the kvo triggered).

Then when the kvo is observed, add the object to the array and call an animation function like this:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    self.kvoToDoList insertObject:object atIndex:0];
    // not sure here what you need to remember in order to do the animation, let's say it's just the object
    [self doAnimations];
}

- (void)doAnimations {

    if (self.kvoToDoList.count == 0) return;
    id object = [self.kvoToDoList lastObject];  // FIFO since we insert at index 0
    [self.kvoToDoList removeLastObject];

    [UIView animateWithDuration:someDuration delay:0.0 options:someOptions animations:^{
        // do animations here based on object
    } completion:^(BOOL finished) {
        // call this recursively, but performSelector so we don't wind up the stack
        [self performSelector:@selector(doAnimations) withObject:nil afterDelay:0.0];
    }];
}
danh
  • 62,181
  • 10
  • 95
  • 136
  • that looks good. I think I try this. The other option I thought would be nice is to use a block and save actions for later execution, when an animation hast ended – Fab1n Jan 31 '13 at 18:14
0

Perhaps post a notification in the completion routine of the 1st animation:

UIView animateWithDuration:delay:options:animations:completion:
Dave
  • 7,552
  • 4
  • 22
  • 26
  • that doesn't work, because with KVO the observer method gets called automatically. Ah and I forgot to mention, the KVO method gets called like random, dependent on which data comes first in. – Fab1n Jan 31 '13 at 17:59
  • This will work; I just omitted all the other issues you need to account for. It's not clear if you want to wait for all data to arrive, then perform Animation1 followed by Animation2; or if you want to kick off each animation as soon its data arrives. – Dave Feb 01 '13 at 17:21
  • thats right. I've thought about it and now I understand, what u mean. With the notifications I can control the actions, that have to be done, after animations are done. What I do after the observe method is called: I change (insertion/deletion/update) an array, based on the new Values, coming in in the KVO method. What I've come up with today: I observe the mutableArray either, and get nice change notifications. With these notifications I want to start the animations each time. (I'm mimicking a UITableView in concept, with concurrent inserts/deletes/updates of views - in a scrollView) – Fab1n Feb 01 '13 at 17:45
0

To anser to my own question with a nice idea:
What do you think of an executionQueue or executionBlock?

I thought, I save execution Code to a block-variable, while some animation is going on. In the animation completion block, I look, whether there is a valid executionBlock.

If there is one, execute, if not, do nothing.

Also I need to save the animation state for the block to be loaded, when a async message comes in.

Fab1n
  • 2,103
  • 18
  • 32