NSTimer не запускается при возникновении события uiscrollview
У меня есть UIImageView, размещенный в UIScrollView. В основном этот UIImageView имеет очень большую карту и создал анимацию по предопределенному пути с направленным направлением навигации "стрелки".
Но, всякий раз, когда происходит uiscrollevents, я думаю, что MainLoop зависает, а NSTimer не запускается, а анимация останавливается.
Есть ли существующее свойство, которое решает эту проблему, в UIScrollView, CAKeyFrameAnimation или NSTimer?
//viewDidLoad
self.myTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(drawLines:) userInfo:nil repeats:YES];
- (void)drawLines:(NSTimer *)timer {
CALayer *arrow = [CALayer layer];
arrow.bounds = CGRectMake(0, 0, 5, 5);
arrow.position = CGPointMake(line.x1, line.y1);
arrow.contents = (id)([UIImage imageNamed:@"arrow.png"].CGImage);
[self.contentView.layer addSublayer:arrow];
CAKeyframeAnimation* animation = [CAKeyframeAnimation animation];
animation.path = path;
animation.duration = 1.0;
animation.rotationMode = kCAAnimationRotateAuto; // object auto rotates to follow the path
animation.repeatCount = 1;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.fillMode = kCAFillModeForwards;
[arrow addAnimation:animation forKey:@"position"];
}
Ответы
Ответ 1
Приложения iOS запускаются на NSRunLoop. Каждый NSRunLoop имеет разные способы выполнения для разных задач. Например, по умолчанию nstimer планируется запустить под NSDefaultRunMode на NSRunLoop. Это означает, однако, что некоторые UIEvents, скроллинг, один из них, прерывают таймер и помещают его в очередь для запуска, как только событие перестает обновляться. В вашем случае, чтобы таймер не прерывался, вам нужно запланировать его для другого режима, а именно NSRunLoopCommonModes, например:
self.myTimer = [NSTimer scheduledTimerWithTimeInterval:280
target:self
selector:@selector(doStuff)
userInfo:nil
repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:self.myTimer forMode:NSRunLoopCommonModes];
Этот режим позволит вашему таймеру не прерываться прокруткой.
Вы можете найти более подробную информацию об этом здесь: https://developer.apple.com/documentation/foundation/nsrunloop
Внизу вы увидите определения режимов, которые вы можете выбрать. Кроме того, у легенды есть это, вы можете писать свои собственные режимы, но мало кто когда-либо жил, чтобы рассказать рассказ, который испугался.
Ответ 2
Еще одна вещь (с)
- используйте метод timerWithTimeInterval, чтобы избежать добавления таймера к циклу выполнения в DefaultMode
- использовать mainRunLoop
Так:
self.myTimer = [NSTimer timerWithTimeInterval: 280 target: self selector: @selector (doStuff) userInfo: nil повторяется: НЕТ]; [[NSRunLoop mainRunLoop] addTimer: self.myTimer forMode: NSRunLoopCommonModes];