将“被盗”的UILabel图层添加到其他CALayer的子图层是否安全?

时间:2014-04-19 15:19:50

标签: ios objective-c uilabel calayer

我看过thisthis,但他们似乎无法解决这个问题。 this的答案似乎与NSCoding和朋友的切线相关,所以......

考虑:

- (NSAttributedString *) attributedStringForText: (NSString *) text {
    NSMutableAttributedString* attrStr = [[NSMutableAttributedString alloc] initWithString:text];
    UIFont * bigF = [UIFont fontWithName:@"OpenSans-Extrabold" size:20.0f] ;
    UIFont * smaF = [UIFont fontWithName:@"OpenSans-Extrabold" size:12.0f] ;

    [attrStr addAttribute:NSFontAttributeName value:bigF range:(NSRange){0, 3}] ;
    [attrStr addAttribute:NSFontAttributeName value:smaF range:(NSRange){3, 6}] ;
    [attrStr addAttribute:NSFontAttributeName value:bigF range:(NSRange){6, [text length]-6}] ;

    [attrStr addAttribute:NSBackgroundColorAttributeName value:[UIColor brownColor] range:(NSRange){3, 6}] ;
    return attrStr ;
}

- (CALayer *) stealLayerFromUILabelForText: (NSString *) text inRect: (CGRect) bounds {
    UILabel * label = [[UILabel alloc] initWithFrame:bounds] ;
    label.textColor = [UIColor whiteColor] ;
    label.font = [UIFont fontWithName:@"OpenSans-Extrabold" size:20.0f] ;
    label.attributedText = [self attributedStringForText:text] ;
    [label sizeToFit] ;
    [label.layer display] ; // Yup!
    return label.layer ;
}

- (void) setupLayer: (CALayer *) tileLayer
               text: (NSString *) text
              index: (NSUInteger) index {

    CGRect (^center_rect)(CGRect, CGRect) = ^CGRect (CGRect r, CGRect into) {
        CGRect centered = into ;
        centered.origin.x += (into.size.width - r.size.width) / 2.0f ;
        centered.origin.y += (into.size.height - r.size.height) / 2.0f ;
        centered.size = r.size ;
        return centered ;
    } ;

    CALayer * layer = [self stealLayerFromUILabelForText:text inRect:tileLayer.bounds] ;
    CGRect frame = center_rect(layer.bounds, tileLayer.bounds) ;

    [tileLayer addSublayer:layer] ;

    layer.frame = frame ;
}

这有效:

enter image description here

但我担心我在某种程度上滥用UILabel& CALayer的。一方面,UIViewUILabel和所有只是真正的 CALayer层次结构上的触摸感知单板。 OTOH我在某种程度上依赖于许多甚至没有说明的假设。

任何人都会看到为什么会在未来发生这种情况,或者更好的是,它可以证明它不会成功?

2 个答案:

答案 0 :(得分:1)

我从2013年开始使用这种技术,但它仍然稳定。是的,我认为现在这是安全的。以前我这样做没有在iOS 4或5上调用-display,在针对较新的SDK进行编译时不再有效,所以感谢这一点。

如果您正在寻找其他选项,可以在此处获取更多信息:Add text to CALayer

答案 1 :(得分:0)

此技术在iOS 10中仍然有效.IMO UIView(在本例中为UILabel)只是其支持CALayer的委托,因此直接操作底层CALayer应该是安全的。唯一的问题是如果您不将标签添加为子视图,标签将被释放,底层的layer.delegate将变为nil,文本永远不会有机会被渲染。

因此我们需要一种在标签发布之前强制渲染的方法。但值得一提的是,不应根据Apple的文档直接调用[CALayer display]。因此,基于相同的想法,考虑一个安全的替代[CALayer displayIfNeeded]

- (CALayer *) stealLayerFromUILabelForText: (NSString *) text inRect: (CGRect) bounds {
    UILabel * label = [[UILabel alloc] initWithFrame:bounds] ;
    label.textColor = [UIColor whiteColor] ;
    label.font = [UIFont fontWithName:@"OpenSans-Extrabold" size:20.0f] ;
    label.attributedText = [self attributedStringForText:text] ;
    [label sizeToFit] ;
    [label.layer displayIfNeeded] ;
    return label.layer ;
}