我看过this和this,但他们似乎无法解决这个问题。 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 ;
}
这有效:
但我担心我在某种程度上滥用UILabel& CALayer的。一方面,UIView
,UILabel
和所有只是真正的 CALayer
层次结构上的触摸感知单板。 OTOH我在某种程度上依赖于许多甚至没有说明的假设。
任何人都会看到为什么会在未来发生这种情况,或者更好的是,它可以证明它不会成功?
答案 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 ;
}