framework - uikit ios
iOS 10.3: NSStrikethroughStyleAttributeName no se representa si se aplica a un subrango de NSMutableAttributedString (6)
Un tachado (simple, doble, ...) agregado como atributo a una instancia de
NSMutableAttributedString
no se representa si el rango de aplicación no es el rango completo de la cadena.
Esto sucede usando
addAttribute(_ name: String, value: Any, range: NSRange)
,
insert(_ attrString: NSAttributedString, at loc: Int)
,
append(_ attrString: NSAttributedString)
, ...
Roto por Apple a principios de iOS 10.3 betas, y no arreglado en 10.3 final.
Swift 4
let text = "Hello World"
let textRange = NSMakeRange(0, text.count)
let attributedText = NSMutableAttributedString(string: text)
attributedText.addAttribute(NSAttributedStringKey.strikethroughStyle,
value: NSUnderlineStyle.styleSingle.rawValue,
range: textRange)
myLabel.attributedText = attributedText
Agregar un
NSBaselineOffsetAttributeName
, como se explica
here
, a la cadena atribuida devuelve la línea tachada.
Al
drawText:in:
puede ser lento, especialmente en las celdas de Vista de colección o Vista de tabla.
Encontramos una solución para nuestro escenario específico (no especificamos ningún estilo con las propiedades de UILabel, pero todos con atributos
NSAttributedString
):
/// This UILabel subclass accomodates conditional fix for NSAttributedString rendering broken by Apple in iOS 10.3
final class PriceLabel: UILabel {
override func drawText(in rect: CGRect) {
guard let attributedText = attributedText else {
super.drawText(in: rect)
return
}
if #available(iOS 10.3, *) {
attributedText.draw(in: rect)
} else {
super.drawText(in: rect)
}
}
}
NOTA: si combina las propiedades de estilo de
NSAttributedString
con los atributos de
NSAttributedString
, debe pensar en crear una nueva cadena de atributos antes de renderizar, aplicar el estilo de UILabel en ella y luego volver a aplicar todos los
attributedText
atribuText sobre ella.
Es un error conocido por Xcode 8.3 (8E3004b) / iOS 10.3, con esta solución alternativa NO se necesita una línea de código adicional, solo agregue
[NSBaselineOffsetAttributeName:0]
al declarar
NSMutableAttributedString()
let attrStr = NSMutableAttributedString(string: YOUR_STRING_HERE, attributes: [NSBaselineOffsetAttributeName : 0])
// Now if you add the strike-through attribute to a range, it will work
attrStr.addAttributes([
NSFontAttributeName: UIFont.boldSystemFont(ofSize: 24),
NSStrikethroughStyleAttributeName: 1
], range: NSRange)
Establecer el desplazamiento de la línea base parece solucionarlo:
[attributedStr addAttribute:NSBaselineOffsetAttributeName value:@0 range:NSMakeRange(0, 10)];
[attributedStr addAttribute:NSStrikethroughStyleAttributeName value:@2 range:NSMakeRange(0, 10)];
Este es un bug conocido en iOS 10.3
código de trabajo swift 3 probado con 10.3
let attributeString: NSMutableAttributedString = NSMutableAttributedString(string: "₹3500")
attributeString.addAttribute(NSBaselineOffsetAttributeName, value: 0, range: NSMakeRange(0, attributeString.length))
attributeString.addAttribute(NSStrikethroughStyleAttributeName, value: 1, range: NSMakeRange(0, attributeString.length))
productPriceLabel.attributedText = attributeString