2015-05-29 1 views
1

У меня есть mapView, который имеет 34 CAShapeLayer для рендеринга каждой провинции и еще 34 CATextLayer для отображения имени для каждой провинции. Я вычислил его центр для каждой провинции.CATextLayer по-прежнему находится в подслоях после вызова removeFromSuperlayer

Теперь я добавляю этот mapView в UIScrollView, и когда я масштабирую mapView, я хочу повторно рисовать CATextLayer, чтобы использовать другой размер шрифта. Поэтому после масштабирования я вручную удалю все CATextLayer и перерисовываю их, как показано ниже.

Однако, я обнаружил, что после завершения цикла for все еще есть CATextLayer в подслоях, а точнее, каждый раз, когда я его тестирую, 18 CATextLayer не удаляется. Я никогда не встречал эту проблему, я что-то пропустил? Пожалуйста, помогите, спасибо.

-(void)drawLabelsWithFontSize:(CGFloat)fontSize { 
    int i = 0; 
    NSUInteger count = [self.mapView.layer.sublayers count]; 
    for (i = 0; i < count; i++) { 
     CALayer *layer = self.mapView.layer.sublayers[i]; 
     if ([layer isKindOfClass:[CATextLayer class]]) { 
      [layer removeFromSuperlayer]; 
      // NSLog(@"%@, %lu",[layer class],i); 
     } else { 
      // NSLog(@"%@",[layer class]); 
     } 
    } 
    // at here, some CATextLayer still in self.mapView.layer.sublayers 
    __block typeof(self) weakSelf = self; 
    NSDictionary *labelNameAndLocation = [self getLabelNameAndLocationInfo]; 
    NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 
    paragraphStyle.alignment = NSTextAlignmentCenter; 
    [labelNameAndLocation enumerateKeysAndObjectsWithOptions:NSEnumerationReverse usingBlock:^(id key, id obj, BOOL *stop) { 
     if ([(NSString *)key length] > 0) { 
      NSDictionary *location = (NSDictionary *)obj; 
      CATextLayer *label = [CATextLayer layer]; 
      CGPoint caculateCenter = CGPointMake([weakSelf longitudeToCoordinate:[location[@"lng"] doubleValue]],[weakSelf latitudeToCoordinate:[location[@"lat"] doubleValue]]); 
      NSMutableAttributedString *text = [[NSMutableAttributedString alloc] 
                initWithString:key 
                attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize], 
                    NSParagraphStyleAttributeName:paragraphStyle, 
                    NSForegroundColorAttributeName:[UIColor blackColor]}]; 
      CGSize size = [text size]; 
      [label setBounds:CGRectMake(0, 0, size.width, size.height)]; 
      [label setString:text]; 
      label.position = caculateCenter; 
      label.contentsScale = [[UIScreen mainScreen] scale]; 
      [weakSelf.mapView.layer addSublayer:label]; 
     } 
    }]; 
} 

ответ

0

Вы делаете классическую ошибку перебора во время удаления:

for (i = 0; i < count; i++) { 
    CALayer *layer = self.mapView.layer.sublayers[i]; 
    if ([layer isKindOfClass:[CATextLayer class]]) { 
     [layer removeFromSuperlayer]; 
     // NSLog(@"%@, %lu",[layer class],i); 
    } else { 
     // NSLog(@"%@",[layer class]); 
    } 
} 

Изменить что for линии итерации вниз:

for (i = count-1; i >= 0; i--) { 

Причина заключается в том, что если вы начиная с удаления, скажем, подслоя 0, все остальные подслои перемещаются вниз по одному индексу. Таким образом, если вы удаляете подуровень 0 и подуровень 1 также является текстовым слоем, этот текстовый слой теперь является подслоем 0 и никогда не будет удален, потому что вы перейдете на подуровень 1. Таким образом, как вы совершенно справедливо продемонстрируете, из них.

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

+0

Кстати, вы не должны рассматривать 'i' как' int', когда 'count' является NSUInteger. Они очень разные животные! Я удивлен, что компилятор не похлопывает вас по этому поводу. 'i' должен быть NSInteger, а не' int'. – matt

+0

Как я могу быть таким глупым, не осознавая этого? Это моя плохая привычка использовать int, я изменю ее. спасибо матовый! Вы всегда сохраняете мой день – Wingzero

+0

И вам не нужно декларировать его отдельно. Вы можете написать 'for (NSInteger i = ...)', и поэтому 'i' является чисто локальным для блока. – matt