Метод доступа после завершения анимации UIImageView
У меня есть массив изображений, загружаемых в UIImageView, которые я анимация через один цикл. После того, как изображения были отображены, я хотел бы, чтобы @selector
, чтобы отклонить текущий controller представления. Изображения анимируются с помощью этого кода:
NSArray * imageArray = [[NSArray alloc] initWithObjects: [UIImage imageNamed:@"HowTo1.png"], [UIImage imageNamed:@"HowTo2.png"], nil]; UIImageView * instructions = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; instructions.animationImages = imageArray; [imageArray release]; instructions.animationDuration = 16.0; instructions.animationRepeatCount = 1; instructions.contentMode = UIViewContentModeBottomLeft; [instructions startAnimating]; [self.view addSubview:instructions]; [instructions release];
Через 16 секунд я хотел бы вызвать метод. Я просмотрел UIView
classа setAnimationDidStopSelector:
но я не могу заставить его работать с моей текущей реализацией анимации. Какие-либо предложения?
Благодарю.
- Ошибка с NSJSONSerialization - Недопустимый тип записи JSON (меню)
- Аккордеонная ячейка таблицы - Как динамически расширять / сокращать uitableviewcell?
- Как установить плагин Xcode для автоматического форматирования кода
- Как я могу перебирать все подпункты UIView, а также их подзоны и их подпрограммы
- Одновременные распознаватели жестов в Iphone SDK
- как отобразить тестовый баннер IAd в симуляторе
- Выполнение команд оболочки с помощью NSTask - Objective-C Cocoa
- Как предоставить пространство между двумя ячейками в виде таблицы?
- как скрыть навигационную панель, когда я нажимаю навигационный controller?
- Как сделать кнопку перехвата надписью для перехвата событий?
- AVAudioPlayer не воспроизводит звук
- NULL против нуля в Objective-C
- Как установить жирный шрифт и курсив на UILabel iPhone / iPad?
Использовать performSelector:withObject:afterDelay:
::
[self performSelector:@selector(animationDidFinish:) withObject:nil afterDelay:instructions.animationDuration];
или используйте dispatch_after
:
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, instructions.animationDuration * NSEC_PER_SEC); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ [self animationDidFinish]; });
Вы можете просто использовать эту категорию UIImageView-AnimationCompletionBlock
И для версии Swift : UIImageView-AnimationImagesCompletionBlock
Посмотрите файл ReadMe в этом classе.
Добавьте файлы проекта UIImageView + AnimationCompletion.h и UIImageView + AnimationCompletion.m в проект, и они импортируют файл UIImageView + AnimationCompletion.h, где вы хотите использовать это.
Напр.
NSMutableArray *imagesArray = [[NSMutableArray alloc] init]; for(int i = 10001 ; i<= 10010 ; i++) [imagesArray addObject:[UIImage imageNamed:[NSString stringWithFormat:@"%d.png",i]]]; self.animatedImageView.animationImages = imagesArray; self.animatedImageView.animationDuration = 2.0f; self.animatedImageView.animationRepeatCount = 3; [self.animatedImageView startAnimatingWithCompletionBlock:^(BOOL success){ NSLog(@"Animation Completed",);}];
Нет никакого способа сделать это именно с UIImageView. Использование задержки будет работать большую часть времени, но может возникнуть некоторое отставание после запуска. Вызывается, когда анимация происходит на экране, поэтому она неточна. Вместо использования UIImageView для этой анимации попробуйте использовать CAKeyframeAnimation, которая вызовет метод делегата, когда анимация будет закончена. Что-то в этом роде:
NSArray * imageArray = [[NSArray alloc] initWithObjects: (id)[UIImage imageNamed:@"HowTo1.png"].CGImage, (id)[UIImage imageNamed:@"HowTo2.png"].CGImage, nil]; UIImageView * instructions = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; //create animation CAKeyframeAnimation *anim = [CAKeyframeAnimation animation]; [anim setKeyPath:@"contents"]; [anim setValues:imageArray]; [anim setRepeatCount:1]; [anim setDuration:1]; anim.delegate = self; // delegate animationDidStop method will be called CALayer *myLayer = instructions.layer; [myLayer addAnimation:anim forKey:nil];
Затем просто реализуйте метод делегирования animationDidStop
С помощью этого метода вы избегаете срабатывания таймеров, пока изображениеView все еще оживляет из-за медленной загрузки изображения. Вы можете использовать как performSelector: withObject: afterDelay:
и GCD таким образом:
[self performSelector:@selector(didFinishAnimatingImageView:) withObject:imageView afterDelay:imageView.animationDuration];
/! \ self.imageView.animationDuration
нужно сделать ставку до startAnimating
, иначе будет 0
Чем if -(void)didFinishAnimatingImageView:
создайте фоновую очередь, выполните проверку свойства isAnimating
, чем выполните остальные в основной очереди
- (void)didFinishAnimatingImageView:(UIImageView*)imageView { dispatch_queue_t backgroundQueue = dispatch_queue_create("com.yourcompany.yourapp.checkDidFinishAnimatingImageView", 0); dispatch_async(backgroundQueue, ^{ while (self.imageView.isAnimating) NSLog(@"Is animating... Waiting..."); dispatch_async(dispatch_get_main_queue(), ^{ /* All the rest... */ }); }); }
Вы можете создать таймер для запуска после продолжительности анимации. Обратный вызов может обрабатывать вашу логику, которую вы хотите выполнить после завершения анимации. В своем [UIImageView isAnimating]
обязательно проверьте статус анимации [UIImageView isAnimating]
на случай, если вам нужно больше времени, чтобы завершить анимацию.
Создана версия Swift из GurPreet_Singh Ответ (UIImageView + AnimationCompletion) Я не смог создать расширение для UIImageView, но считаю, что это достаточно просто для использования.
class AnimatedImageView: UIImageView, CAAnimationDelegate { var completion: ((_ completed: Bool) -> Void)? func startAnimate(completion: ((_ completed: Bool) -> Void)?) { self.completion = completion if let animationImages = animationImages { let cgImages = animationImages.map({ $0.cgImage as AnyObject }) let animation = CAKeyframeAnimation(keyPath: "contents") animation.values = cgImages animation.repeatCount = Float(self.animationRepeatCount) animation.duration = self.animationDuration animation.delegate = self self.layer.add(animation, forKey: nil) } else { self.completion?(false) } } func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { completion?(flag) } } let imageView = AnimatedImageView(frame: CGRect(x: 50, y: 50, width: 200, height: 135)) imageView.image = images.first imageView.animationImages = images imageView.animationDuration = 2 imageView.animationRepeatCount = 1 view.addSubview(imageView) imageView.startAnimate { (completed) in print("animation is done \(completed)") imageView.image = images.last }
в ImageView.m
- (void) startAnimatingWithCompleted:(void (^)(void))completedHandler { if (!self.isAnimating) { [self startAnimating]; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, self.animationDuration * NSEC_PER_SEC); dispatch_after(popTime, dispatch_get_main_queue(),completedHandler); }}