2

我有一个 mapView,它有 34 个 CAShapeLayer 来渲染每个省,另外 34 个 CATextLayer 来渲染每个省的名称。我将计算每个省的中心。

现在我将此 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];
        }
    }];
}
4

1 回答 1

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。因此,正如您非常正确地证明的那样,您最终会丢失一半其中。

我有点惊讶,事实上,你并没有因此而崩溃,但我猜有这么多子层,你只是从来没有从数组的末端掉下来;崩溃是通常发生的事情。

于 2015-05-29T01:29:37.813 回答