Очередь анимации iOS для полученных сообщений
У меня есть простая анимация, которая запускается при получении сообщения. Это прекрасно работает, если они получают только одно сообщение. Однако если пользователь получает несколько сообщений в рамках анимации, анимация начинается заново. Я не хочу, чтобы это случилось, я хочу, чтобы анимация закончилась до начала следующей. Я думал создать некую очередь, которая будет проходить по словарю с ключами from и body, но я не уверен, что это лучший метод. У кого-нибудь есть какие-либо идеи?
- (void) messageReceived:(NSNotification *)notification
{
NSString *body = [[notification userInfo] valueForKey:@"body"];
NSString *from = [[notification userInfo] valueForKey:@"from"];
UILabel *usernameLabel = (UILabel *)[self.view viewWithTag:502];
usernameLabel.text = from;
UILabel *messageLabel = (UILabel *)[self.view viewWithTag:503];
messageLabel.text = body;
CGRect notificationFrame = notificationView.frame;
notificationFrame.origin.y = 0;
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
notificationView.frame = notificationFrame;
}
completion:^(BOOL finished){
if (finished) {
[UIView animateWithDuration:0.3
delay:1.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
CGRect oldNotificationFrame = notificationView.frame;
oldNotificationFrame.origin.y = -100;
notificationView.frame = oldNotificationFrame;
}
completion:NULL];
}
}];
}
1 ответ
Я думаю, что вам нужен двусторонний подход; создавать и помещать сообщения в очередь, а затем анимировать сообщение, ЕСЛИ одно или несколько сообщений уже помещены в очередь для анимации; в этом случае просто поставьте в очередь анимацию. Когда анимация заканчивается, блок завершения будет повторяться до тех пор, пока очередь не станет пустой.
@implementation yourCLass {
// holds incoming animation requests in FIFO order
NSMutableArray *animationQueue;
// control switch to avoid starting an animation if one is running
BOOL isAnimating;
}
- (void) messageReceived:(NSNotification *)notification {
// pertinent message data is stored in a dict in the array
NSString *body = [[notification userInfo] valueForKey:@"body"];
NSString *from = [[notification userInfo] valueForKey:@"from"];
NSDictionary *messageFacts = @{ @"body" : body,
@"from" : from };
// most-recent messages get put into position zero; LIFO
// NB: this array has already been initialized elsewhere...
[self->animationQueue insertObject:messageFacts
atIndex:0];
// now for animating BUT ONLY if not already animating (if already animating the queued
// animations will get animated anyway)
if (!self->isAnimating) {
[self animateMessages];
}
}
- (void) animateMessages {
if (self->animationQueue.count == 0) {
// all messages have been animated, clear isAnimating bit and exit
self->isAnimating = NO;
return;
}
self->isAnimating = YES;
// extract message data from array as a dictionary, delete from array
NSDictionary *messageFacts = [self->animationQueue lastObject];
[self->animationQueue removeLastObject];
// import message data from dictionary to labels
UILabel *usernameLabel = (UILabel *)[self.view viewWithTag:502];
usernameLabel.text = messageFacts[@"from"];
UILabel *messageLabel = (UILabel *)[self.view viewWithTag:503];
messageLabel.text = messageFacts[@"body"];
// other housekeeping
CGRect notificationFrame = notificationView.frame;
notificationFrame.origin.y = 0;
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
notificationView.frame = notificationFrame;
}
completion:^(BOOL finished){
if (finished) {
[UIView animateWithDuration:0.3
delay:1.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
CGRect oldNotificationFrame = notificationView.frame;
oldNotificationFrame.origin.y = -100;
notificationView.frame = oldNotificationFrame;
}
completion:^(BOOL finished){
if (finished ) {
// when done, method recurs until all notifications have
// been animated
[self animateMessages];
}
}];
}
}];
}