2016-09-06 4 views
1

Я использую EFCircularSlider, чтобы отобразить круговую линию и пользователь будет двигаться обработчик следующим образом:Почему CGContext не рисует петлю?

Я выполнил все требования пользователей, за исключением отображения красной линии поведения анимации. Я не могу сильно изменить свой код. Я пытаюсь постепенно нарисовать эту линию дуги. Вместо использования анимации я использую CGContext и показываю круг в цикле. Но он рисует изображение в конце цикла. У меня есть прослеживать его вниз и убедились, что петля вызывался правильно следующим образом:

Я вызываю метод:

int tmp = self.angleFromNorth; 
    while (tmp<360) { 
     NSLog(@"tmp == %d",tmp); 
     tmp+=10; 
     [NSThread sleepForTimeInterval: 0.1]; 
     [EFCircularTrig drawUnfilledArcInContext:ctx 
              center:self.centerPoint 
              radius:self.radius 
             lineWidth:self.lineWidth 
           fromAngleFromNorth:self.angleFromNorth 
           toAngleFromNorth:tmp]; 
      [self setNeedsDisplay]; 
    } 

И тогда он будет печатать строку правильно, но только после того, как цикл закончен. При распечатке всех значений он отобразит строку. Но я хочу сделать его похожим на анимацию.

+(void) drawUnfilledArcInContext:(CGContextRef)ctx 
          center:(CGPoint)center 
          radius:(CGFloat)radius 
         lineWidth:(CGFloat)lineWidth 
       fromAngleFromNorth:(CGFloat)fromAngleFromNorth 
       toAngleFromNorth:(CGFloat)toAngleFromNorth 
{ 

    float cartesianFromAngle = CompassToCartesian(ToRad(fromAngleFromNorth)); 
    float cartesianToAngle = CompassToCartesian(ToRad(toAngleFromNorth)); 

    CGContextAddArc(ctx, 
        center.x, // arc start point x 
        center.y, // arc start point y 
        radius,  // arc radius from center 
        cartesianFromAngle, cartesianToAngle, 
        0); // iOS flips the y coordinate so anti-clockwise (specified here by 0) becomes clockwise (desired)! 

    CGContextSetLineWidth(ctx, lineWidth); 
    CGContextSetLineCap(ctx, kCGLineCapButt); 
    CGContextSetShadowWithColor(ctx, CGSizeMake(0,0), 1, [UIColor colorWithRed:(0/255.0) green:(173/255.0) blue:(238/255.0) alpha:1.0].CGColor); 
    CGContextDrawPath(ctx, kCGPathStroke); 

    NSLog(@"HERE"); 
} 

Выход:

2016-09-06 22:52:48.950 EFCircularSlider[38301:288182] tmp == 22 
2016-09-06 22:52:49.056 EFCircularSlider[38301:288182] HERE 
2016-09-06 22:52:49.056 EFCircularSlider[38301:288182] tmp == 32 
2016-09-06 22:52:49.161 EFCircularSlider[38301:288182] HERE 
2016-09-06 22:52:49.162 EFCircularSlider[38301:288182] tmp == 42 
2016-09-06 22:52:49.265 EFCircularSlider[38301:288182] HERE 
2016-09-06 22:52:49.266 EFCircularSlider[38301:288182] tmp == 52 
2016-09-06 22:52:49.371 EFCircularSlider[38301:288182] HERE 
2016-09-06 22:52:49.372 EFCircularSlider[38301:288182] tmp == 62 
2016-09-06 22:52:49.475 EFCircularSlider[38301:288182] HERE 
2016-09-06 22:52:49.475 EFCircularSlider[38301:288182] tmp == 72 
2016-09-06 22:52:49.580 EFCircularSlider[38301:288182] HERE 

Но рисунок будет появляться после того, как цикл завершается. Я хочу, чтобы он появился постепенно. Я ценю, если кто-то может добавить свой опыт здесь.

Я также добавил:

ответ

1

В конце цикла обработки событий (после того, как drawRect вернулся), все, что в контексте будет состоять на экран. До конца цикла событий вы просто изменяете контекст, а не экран. Все setNeedsDisplay действительно говорит: «В следующий раз, когда цикл событий запущен, это представление нужно снова нарисовать». На самом деле он ничего не делает.

Ваш подход не может работать. Если вы вызываете sleepForTimeInterval: в основной поток (или вообще любой поток), вы абсолютно не соответствуете этой проблеме. На iOS, если вы сделаете это слишком долго, ОС убьет ваше приложение.

Вам необходимо анимировать свой путь. Это, как правило, лучше всего сделать путем анимации CAShapeLayer (свойства strokeStart и strokeEnd могут быть анимированы). Вы захотите создать путь, а не рисовать дугу. Есть много интродукций для такого рода анимации, например, см. Ole Begemann's Animating the Drawing of a CGPath with CAShapeLayer.

Короткая версия, однако, является то, что вы должны преобразовать ваши заявления отрисовки в вызовы на UIBezierPath или CGPath нарисовать всю дугу, а затем использовать CABasicAnimation, чтобы оживить его.