2012-06-20 3 views
2

У меня очень большой UIView размером около 3000x3000. В этом большом представлении я делаю несколько бесплатных рисунков с помощью стилуса или пальца на iPad. Вот мой код для моих прикосновений начал и перемещал методы.setNeedsDisplay на большом UIView, вызывающем

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{  

     Line_Point * to_be_added = [[Line_Point alloc] init]; 
     to_be_added.line_color = [UIColor colorWithCGColor: current_color.CGColor]; 
     to_be_added.line_pattern = [NSString stringWithString: current_line_pattern]; 

     UITouch *touch = [[event touchesForView:self] anyObject]; 

     CGPoint location = [touch locationInView:self]; 
     to_be_added.point = [NSValue valueWithCGPoint:(location)]; 

     if (self.points == nil) 
     { 
      NSMutableArray *newPoints = [[NSMutableArray alloc] init]; 
      self.points = newPoints; 
      [newPoints release]; 
     } 

     [self.points addObject:to_be_added];   



} 

Вот мои прикосновения перемещается метод, который, кажется, вызывает проблемы, потому что оно не вызывался достаточно, потому что приложение вызывает setNeedsDisplay

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 

     Line_Point * to_be_added = [[Line_Point alloc] init]; 
     to_be_added.line_color = [UIColor colorWithCGColor: current_color.CGColor]; 
     to_be_added.line_pattern = [NSString stringWithString: current_line_pattern]; 

     UITouch * touch = [[event touchesForView:self] anyObject]; 
     CGPoint location = [touch locationInView:self]; 
     to_be_added.point = [NSValue valueWithCGPoint:(location)]; 

     [self.points addObject:to_be_added];   


     [self setNeedsLayout]; 

} 

Теперь вот мой метод DrawRect который отображает рисунок

-(void)drawRect:(CGRect)rect 
{ 
if (self.points.count == 0)   
    { 

    } 
    else 
    {  
     Line_Point * first = [self.points objectAtIndex:0]; 
     CGContextRef context2 = UIGraphicsGetCurrentContext(); 
     CGContextSetStrokeColorWithColor(context2, first.line_color.CGColor); 
     if ([first.line_pattern isEqualToString:@"normal"]) 
     { 
      CGContextSetLineWidth(context2, 4.0); 
      CGContextSetLineDash(context2, 0, NULL, 0); 
     } 
     else if([first.line_pattern isEqualToString:@"thick"])    
     { 
      CGContextSetLineWidth(context2, 6.0); 
      CGContextSetLineDash(context2, 0, NULL, 0); 
     } 
     else if([first.line_pattern isEqualToString:@"dotted"])    
     { 
      CGFloat Pattern[] = {5, 5, 5, 5}; 
      CGContextSetLineDash(context2, 0, Pattern, 4); 
     } 
     else if([first.line_pattern isEqualToString:@"super_dotted"])    
     { 
      CGFloat Pattern[] = {1, 2, 1, 2}; 
      CGContextSetLineDash(context2, 0, Pattern, 4); 
     }   
     CGPoint firstPoint2 = [first.point CGPointValue]; 
     CGContextBeginPath(context2); 
     CGContextMoveToPoint(context2, firstPoint2.x, firstPoint2.y); 

     int i2 = 1; 
     while (i2 < self.points.count) 
     { 
      Line_Point * nextPoint = [self.points objectAtIndex:i2]; 

      if (nextPoint.point.CGPointValue.x < 0 && nextPoint.point.CGPointValue.y < 0) 
      { 
       CGContextDrawPath(context2, kCGPathStroke); 

       if (i2 < (self.points.count-1)) 
       { 

        CGContextBeginPath(context2); 
        Line_Point * nextPoint2 = [self.points objectAtIndex:i2+1];     
        CGContextMoveToPoint(context2, nextPoint2.point.CGPointValue.x, nextPoint2.point.CGPointValue.y); 
        CGContextSetStrokeColorWithColor(context2, nextPoint2.line_color.CGColor); 
        if ([nextPoint2.line_pattern isEqualToString:@"normal"]) 
        { 
         CGContextSetLineWidth(context2, 4.0); 
         CGContextSetLineDash(context2, 0, NULL, 0); 
        } 
        else if([nextPoint2.line_pattern isEqualToString:@"thick"])    
        { 
         CGContextSetLineWidth(context2, 6.0); 
         CGContextSetLineDash(context2, 0, NULL, 0); 
        } 
        else if([nextPoint2.line_pattern isEqualToString:@"dotted"])    
        { 
         CGFloat Pattern[] = {5, 5, 5, 5}; 
         CGContextSetLineDash(context2, 0, Pattern, 4); 
        } 
        else if([nextPoint2.line_pattern isEqualToString:@"super_dotted"])    
        { 
         CGFloat Pattern[] = {1, 2, 1, 2}; 
         CGContextSetLineDash(context2, 0, Pattern, 4); 
        }   
        i2 = i2 + 2; 

       } 
       else 
        i2++; 
      } 
      else 
      { 
       CGContextAddLineToPoint(context2, nextPoint.point.CGPointValue.x, nextPoint.point.CGPointValue.y); 
       i2++; 
      } 
     } 

     CGContextDrawPath(context2, kCGPathStroke); 
    } 

Приложение небрежно ломается при рисовании в режиме свободной формы. Я считаю, что это связано с тем, что представление слишком велико и setNeedsDisplay перезагружает весь вид каждый раз, когда вызывается метод перемещений касаний. Есть ли способ ускорить метод setNeedsDisplay, поэтому рисунок бесплатной формы не отстает от iPad. Могу ли я просто настроить контекст, в котором происходит рисование, не перезагружать все это? Когда я настраиваю размер до 1000x1000, у него нет проблемы с задержкой.

Спасибо за любую помощь по этому вопросу.

EDIT судимое ИСПОЛЬЗОВАНИЕ -SetNeedsDisplayinRect

The UIView обернута внутри UIScrollView и вот код.

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
    { 

    Line_Point * to_be_added = [[Line_Point alloc] init]; 
    to_be_added.line_color = [UIColor colorWithCGColor: current_color.CGColor]; 
    to_be_added.line_pattern = [NSString stringWithString: current_line_pattern]; 

    UITouch * touch = [[event touchesForView:self] anyObject]; 
    CGPoint location = [touch locationInView:self]; 
    to_be_added.point = [NSValue valueWithCGPoint:(location)]; 

    [self.points addObject:to_be_added];   


      CGRect visibleRect; 
     visibleRect.origin = big_view.scrollable_view.contentOffset; 
     visibleRect.size = CGSizeMake(950, 500);    
     [self setNeedsDisplayInRect:visibleRect]; 

} 

Этот метод подхода также не помогает.

Еще раз спасибо, если вы можете помочь.

ответ

2

вы можете использовать

- (void)setNeedsDisplayInRect:(CGRect)invalidRect 

вместо -setNeedsDisplay

другого решения (если есть слишком много точек, и приложение отстает из-за вовлекая их) - не воздавать все точки каждый раз, когда - Вызывается drawInRect. Вы можете, например, при каждом 10-м вызове сохранить изображение из текущего контекста, а затем отобразить только изображение.

Update:

попробуйте добавить

+(Class)layerClass 
{ 
return [CATiledLayer class]; 
} 

на ваш взгляд, в Scrollview

+0

Ive использовал вышеуказанный метод и, похоже, не работал. Прямо не работает. Я даже убедился, что прямой был правильным. Будет редактировать выше код. – Krzemienski

+0

Я нашел это [link] (https://discussions.apple.com/thread/1630986?start=0&tstart=0) и некоторые другие, и они говорят о проблемах с большими видами в scrollView. Я обновлю ответ – medvedNick

+0

AWSOME! Это сработало! – Krzemienski

0

Просто, чтобы сделать это ясно, 3000x3000pixel UIView имеет CALayer позади (не имеет значения, много, если черепицей или нет), который использует пространство 3000x3000x4 байт, так что это примерно 34-35 МБ. Вы не увидите этого использования памяти в самом приложении, так как оно выделено на трамплине.

Лучшее решение с моей точки зрения будет состоять в том, чтобы сложить слои с слоем чуть больше, чем ваш вид (потому что они могут отображать поток), а затем включить обрезку и назначить ваши пути соответствующим смещение к слоям. Это совсем некоторая работа, но все будет хорошо.

Ах, когда-нибудь, вы делаете перерисовку, это помогает очистить кеш CALayers. Уровень layer.contents = nil сделал бы это ....

cheers, Jörg

Смежные вопросы