17

UIScrollViewにUIImageViewを配置しました。基本的に、この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"];
}
4

2 に答える 2

61

iOSアプリケーションはNSRunLoopで実行されます。NSRunLoopごとに、タスクごとに異なる実行モードがあります。たとえば、デフォルトのnstimerは、NSRunLoopのNSDefaultRunModeで実行されるようにスケジュールされています。ただし、これが意味するのは、スクロールビューが1つである特定のUIEventがタイマーを中断し、イベントの更新が停止するとすぐに実行されるキューに配置することです。あなたの場合、タイマーが中断されないようにするには、次のように、別のモード、つまり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 を参照してください。下部に、選択できるモードの定義が表示されます。また、伝説にはそれがあり、独自のカスタムモードを作成できますが、恐れて物語を語るために生きた人はほとんどいません。

于 2012-02-01T06:04:06.160 に答える
1

もう1つ(c)

  1. DefaultModeのrunloopにタイマーを追加しないようにするには、timerWithTimeIntervalメソッドを使用します
  2. mainRunLoopを使用する

それで:

self.myTimer = [NSTimer timerWithTimeInterval:280 target:selfセレクター:@selector(doStuff)userInfo:nil repeats:NO]; [[NSRunLoop mainRunLoop] addTimer:self.myTimer forMode:NSRunLoopCommonModes];

于 2019-07-08T12:41:16.427 に答える