2

各州をレンダリングするための 34 個の CAShapeLayer と、各州の名前をレンダリングするための別の 34 個の CATextLayer を持つ mapView があります。各州の中心を計算します。

この 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その行を iterate downに変更します。

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

その理由は、たとえばサブレイヤー 0 を削除することから始めると、他のすべてのサブレイヤーが 1 インデックス下に移動するためです。したがって、サブレイヤー 0 を削除し、サブレイヤー 1 もテキスト レイヤーである場合、そのテキスト レイヤーはサブレイヤー 0 になり、サブレイヤー 1 に進むため削除されることはありません。そのうちの。

実際、これが原因でクラッシュしていないことに少し驚いていますが、サブレイヤーが非常に多いため、アレイの最後から落ちたことはないと思います。クラッシュは通常発生するものです。

于 2015-05-29T01:29:37.813 に答える