iOS 10.3: NSStrikethroughStyleAttributeName no se representa si se aplica a un rango secundario de NSMutableAttributedString

Un tachado (simple, doble, …) agregado como atributo a una instancia de NSMutableAttributedString no se representa si el rango de aplicación no es todo el rango de cadena.

Esto ocurre usando addAttribute(_ name: String, value: Any, range: NSRange) , insert(_ attrString: NSAttributedString, at loc: Int) , append(_ attrString: NSAttributedString) , …

Broken por Apple en versiones anteriores de iOS 10.3, y no se corrigió en 10.3 final.

Crédito: https://openradar.appspot.com/31034683

Agregar un NSBaselineOffsetAttributeName , como se explica aquí , a la cadena atribuida trae de vuelta la línea tachado. drawText:in: puede ser lento especialmente en Collection View o Table View Cells.

Establecer el desplazamiento de la línea base parece arreglarlo:

 [attributedStr addAttribute:NSBaselineOffsetAttributeName value:@0 range:NSMakeRange(0, 10)]; [attributedStr addAttribute:NSStrikethroughStyleAttributeName value:@2 range:NSMakeRange(0, 10)]; 

Este es un error conocido en iOS 10.3

Se ha encontrado una solución para nuestro escenario específico (no especificamos ningún estilo con las propiedades de UILabel, pero todas 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 mezclas las propiedades de estilo de NSAttributedString con los atributos NSAttributedString , deberías pensar en crear una nueva cadena atribuida antes del renderizado, aplicar el estilo de UILabel en ella y luego volver a aplicar todos los attributedText de attributeText sobre ella.

código de trabajo veloz 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 

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 

Es un error conocido por Xcode 8.3 (8E3004b) / iOS 10.3, con esta solución NO se necesita ninguna línea adicional de código, solo agrega [NSBaselineOffsetAttributeName:0] cuando se declara 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)