teclado tabla superindice subindices subindice poner para pages mac exponentes contenido con como ios swift

ios - tabla - Cómo usar subíndice y superíndice en Swift



superindice iphone (11)

Versión Swift 4+ de la respuesta de @ Atka

import UIKit extension NSMutableAttributedString { enum Scripting : Int { case aSub = -1 case aSuper = 1 } func scripts(string: String, characters: [Character], type: Scripting, stringFont: UIFont, fontSize: CGFloat, scriptFont: UIFont, scriptFontSize: CGFloat, offSet: Int, length: [Int], alignment: NSTextAlignment) -> NSMutableAttributedString { let paraghraphStyle = NSMutableParagraphStyle() paraghraphStyle.alignment = alignment var scriptedCharaterLocation = Int() let attributes = [ NSAttributedStringKey.font: stringFont, NSAttributedStringKey.foregroundColor: UIColor.black, NSAttributedStringKey.paragraphStyle: paraghraphStyle ] let attString = NSMutableAttributedString(string:string, attributes: attributes) let baseLineOffset = offSet * type.rawValue let scriptTextAttributes: [NSAttributedStringKey : Any] = [ NSAttributedStringKey.font: scriptFont, NSAttributedStringKey.baselineOffset: baseLineOffset, NSAttributedStringKey.foregroundColor: UIColor.blue ] for (i,c) in string.enumerated() { for (theLength, aCharacter) in characters.enumerated() { if c == aCharacter { scriptedCharaterLocation = i attString.setAttributes(scriptTextAttributes, range: NSRange(location:scriptedCharaterLocation, length: length[theLength])) } } } return attString } }

Quiero que mi UILabel muestre texto de la siguiente manera 6.022 * 10 23 . ¿Qué funciones tiene swift para subíndice y superíndice?


Aquí hay una solución Swift 5.1 (también debería funcionar con versiones anteriores de Swift) usando recursividad, que solo se enfoca en la salida de un superíndice desde un Int (es decir, sin formato para mostrar).

extension Int { func superscriptString() -> String { let minusPrefixOrEmpty: String = self < 0 ? Superscript.minus : "" let (quotient, remainder) = abs(self).quotientAndRemainder(dividingBy: 10) let quotientString = quotient > 0 ? quotient.superscriptString() : "" return minusPrefixOrEmpty + quotientString + Superscript.value(remainder) } } enum Superscript { static let minus = "⁻" private static let values: [String] = [ "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹" ] static func value(_ int: Int) -> String { assert(int >= 0 && int <= 9) return values[int] } }

Aquí hay algunas pruebas para probar la corrección:

func testPositiveIntegersSuperscript() { XCTAssertEqual(0.superscriptString(), "⁰") XCTAssertEqual(1.superscriptString(), "¹") XCTAssertEqual(2.superscriptString(), "²") XCTAssertEqual(3.superscriptString(), "³") XCTAssertEqual(4.superscriptString(), "⁴") XCTAssertEqual(5.superscriptString(), "⁵") XCTAssertEqual(6.superscriptString(), "⁶") XCTAssertEqual(7.superscriptString(), "⁷") XCTAssertEqual(8.superscriptString(), "⁸") XCTAssertEqual(9.superscriptString(), "⁹") XCTAssertEqual(10.superscriptString(), "¹⁰") XCTAssertEqual(11.superscriptString(), "¹¹") XCTAssertEqual(12.superscriptString(), "¹²") XCTAssertEqual(19.superscriptString(), "¹⁹") XCTAssertEqual(20.superscriptString(), "²⁰") XCTAssertEqual(21.superscriptString(), "²¹") XCTAssertEqual(99.superscriptString(), "⁹⁹") XCTAssertEqual(100.superscriptString(), "¹⁰⁰") XCTAssertEqual(101.superscriptString(), "¹⁰¹") XCTAssertEqual(102.superscriptString(), "¹⁰²") XCTAssertEqual(237.superscriptString(), "²³⁷") XCTAssertEqual(999.superscriptString(), "⁹⁹⁹") XCTAssertEqual(1000.superscriptString(), "¹⁰⁰⁰") XCTAssertEqual(1001.superscriptString(), "¹⁰⁰¹") XCTAssertEqual(1234.superscriptString(), "¹²³⁴") XCTAssertEqual(1337.superscriptString(), "¹³³⁷") } func testNegativeIntegersSuperscript() { XCTAssertEqual(Int(-1).superscriptString(), "⁻¹") XCTAssertEqual(Int(-2).superscriptString(), "⁻²") XCTAssertEqual(Int(-3).superscriptString(), "⁻³") XCTAssertEqual(Int(-4).superscriptString(), "⁻⁴") XCTAssertEqual(Int(-5).superscriptString(), "⁻⁵") XCTAssertEqual(Int(-6).superscriptString(), "⁻⁶") XCTAssertEqual(Int(-7).superscriptString(), "⁻⁷") XCTAssertEqual(Int(-8).superscriptString(), "⁻⁸") XCTAssertEqual(Int(-9).superscriptString(), "⁻⁹") XCTAssertEqual(Int(-10).superscriptString(), "⁻¹⁰") XCTAssertEqual(Int(-11).superscriptString(), "⁻¹¹") XCTAssertEqual(Int(-12).superscriptString(), "⁻¹²") XCTAssertEqual(Int(-19).superscriptString(), "⁻¹⁹") XCTAssertEqual(Int(-20).superscriptString(), "⁻²⁰") XCTAssertEqual(Int(-21).superscriptString(), "⁻²¹") XCTAssertEqual(Int(-99).superscriptString(), "⁻⁹⁹") XCTAssertEqual(Int(-100).superscriptString(), "⁻¹⁰⁰") XCTAssertEqual(Int(-101).superscriptString(), "⁻¹⁰¹") XCTAssertEqual(Int(-102).superscriptString(), "⁻¹⁰²") XCTAssertEqual(Int(-237).superscriptString(), "⁻²³⁷") XCTAssertEqual(Int(-999).superscriptString(), "⁻⁹⁹⁹") XCTAssertEqual(Int(-1000).superscriptString(), "⁻¹⁰⁰⁰") XCTAssertEqual(Int(-1001).superscriptString(), "⁻¹⁰⁰¹") XCTAssertEqual(Int(-1234).superscriptString(), "⁻¹²³⁴") XCTAssertEqual(Int(-1337).superscriptString(), "⁻¹³³⁷") }

Mi solución es más del doble de rápida que la solución de gorillaz (que se basa en cadenas y matrices), gracias a que la mía se basa en matemáticas y recursividad. Aquí está la prueba:

private typealias SuperscriptVector = (value: Int, expectedSuperstring: String) private let vector1to9: SuperscriptVector = (123456789, "¹²³⁴⁵⁶⁷⁸⁹") func performanceTest(times n: Int, function: (Int) -> () -> String) { func manyTimes(_ times: Int) { func doTest(vector: SuperscriptVector) { let result: String = function(vector.value)() XCTAssertEqual(result, vector.expectedSuperstring) } for _ in 0..<times { doTest(vector: vector1to9) } } manyTimes(n) } // 3.244 sec func testPerformanceMine() { measure { performanceTest(times: 1_000_000, function: Int.superscriptString) } } // 7.6 sec func testPerformance() { measure { performanceTest(times: 1_000_000, function: Int.superscriptStringArrayBased) } }


Aquí hay una versión simple que tiene un manejo correcto de errores y se compilará en el patio de recreo.

import UIKit func setMyLabelText(myLabel: UILabel) { if let largeFont = UIFont(name: "Helvetica", size: 20), let superScriptFont = UIFont(name: "Helvetica", size:10) { let numberString = NSMutableAttributedString(string: "6.022*10", attributes: [.font: largeFont]) numberString.append(NSAttributedString(string: "23", attributes: [.font: superScriptFont, .baselineOffset: 10])) myLabel.attributedText = numberString } } let myLabel = UILabel() setMyLabelText(myLabel: myLabel)


Como un enfoque diferente, escribí una función que toma una cadena donde los exponentes se anteponen con ^ como 2^2•3•5^2 y devuelve 2²•3•5²

func exponentize(str: String) -> String { let supers = [ "1": "/u{00B9}", "2": "/u{00B2}", "3": "/u{00B3}", "4": "/u{2074}", "5": "/u{2075}", "6": "/u{2076}", "7": "/u{2077}", "8": "/u{2078}", "9": "/u{2079}"] var newStr = "" var isExp = false for (_, char) in str.characters.enumerate() { if char == "^" { isExp = true } else { if isExp { let key = String(char) if supers.keys.contains(key) { newStr.append(Character(supers[key]!)) } else { isExp = false newStr.append(char) } } else { newStr.append(char) } } } return newStr }

Es un poco un método de fuerza bruta, pero funciona si no desea tratar con cadenas atribuidas o si su cadena es independiente de una fuente.


Creé una clase AmountFormatter que me ayudó a convertir números decimales en números con decimales elevados.

class AmountFormatter { static func sharedFormatter( decimalNumber: NSDecimalNumber, currency: String, raisedDecimals: Bool) -> NSAttributedString { let numberFormatter = NumberFormatter() numberFormatter.usesGroupingSeparator = true numberFormatter.groupingSeparator = "." numberFormatter.decimalSeparator = "," numberFormatter.numberStyle = .decimal let scale: Int16 = 2 let behavior = NSDecimalNumberHandler( roundingMode: .plain, scale: scale, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true) guard let amountString = numberFormatter.string( from: decimalNumber.rounding(accordingToBehavior: behavior)) else { fatalError("Can''t convert conversion from ''NSDecimalNumber'' to string") } let currencyAmountString = currency + amountString let font = UIFont(name: "Roboto", size: 20) let fontSuper = UIFont(name: "Roboto", size: 10) let attributedCurrencyAmountString = NSMutableAttributedString( string: currencyAmountString, attributes: [.font: font!]) if raisedDecimals == false { return attributedCurrencyAmountString as NSAttributedString } var array = attributedCurrencyAmountString.string.split(separator: ",") let lenght = array[0].count attributedCurrencyAmountString.setAttributes( [.font: fontSuper!, .baselineOffset: 10], range: NSRange(location: lenght, length: 3)) attributedCurrencyAmountString.setAttributes( [.font: fontSuper!], range: NSRange(location: 0, length: 1)) return attributedCurrencyAmountString as NSAttributedString } }


Escribí la siguiente extensión o puedes usarla como una función, me está funcionando bien. puedes modificarlo saltando las partes que no son esenciales para ti

extension NSMutableAttributedString { enum scripting : Int { case aSub = -1 case aSuper = 1 } func characterSubscriptAndSuperscript(string:String, characters:[Character], type:scripting, fontSize:CGFloat, scriptFontSize:CGFloat, offSet:Int, length:[Int], alignment:NSTextAlignment)-> NSMutableAttributedString { let paraghraphStyle = NSMutableParagraphStyle() // Set The Paragraph aligmnet , you can ignore this part and delet off the function paraghraphStyle.alignment = alignment var scriptedCharaterLocation = Int() //Define the fonts you want to use and sizes let stringFont = UIFont.boldSystemFont(ofSize: fontSize) let scriptFont = UIFont.boldSystemFont(ofSize: scriptFontSize) // Define Attributes of the text body , this part can be removed of the function let attString = NSMutableAttributedString(string:string, attributes: [NSFontAttributeName:stringFont,NSForegroundColorAttributeName:UIColor.black,NSParagraphStyleAttributeName: paraghraphStyle]) // the enum is used here declaring the required offset let baseLineOffset = offSet * type.rawValue // enumerated the main text characters using a for loop for (i,c) in string.characters.enumerated() { // enumerated the array of first characters to subscript for (theLength,aCharacter) in characters.enumerated() { if c == aCharacter { // Get to location of the first character scriptedCharaterLocation = i //Now set attributes starting from the character above attString.setAttributes([NSFontAttributeName:scriptFont, // baseline off set from . the enum i.e. +/- 1 NSBaselineOffsetAttributeName:baseLineOffset, NSForegroundColorAttributeName:UIColor.black], // the range from above location range:NSRange(location:scriptedCharaterLocation, // you define the length in the length array // if subscripting at different location // you need to define the length for each one length:length[theLength])) } } } return attString} }

ejemplos:

let attStr1 = NSMutableAttributedString().characterSubscriptAndSuperscript( string: "23 x 456", characters:["3","5"], type: .aSuper, fontSize: 20, scriptFontSize: 15, offSet: 10, length: [1,2], alignment: .left)

let attStr2 = NSMutableAttributedString().characterSubscriptAndSuperscript( string: "H2SO4", characters: ["2","4"], type: .aSub, fontSize: 20, scriptFontSize: 15, offSet: 8, length: [1,1], alignment: .left)


He creado una extensión de cadena que toma una cadena y convierte todo su superíndice en caracteres unicode. De esta manera, por ejemplo, podría compartir la cadena resultante sin problemas.

extension Character { var unicode: String { // See table here: https://en.wikipedia.org/wiki/Unicode_subscripts_and_superscripts let unicodeChars = [Character("0"):"/u{2070}", Character("1"):"/u{00B9}", Character("2"):"/u{00B2}", Character("3"):"/u{00B3}", Character("4"):"/u{2074}", Character("5"):"/u{2075}", Character("6"):"/u{2076}", Character("7"):"/u{2077}", Character("8"):"/u{2078}", Character("9"):"/u{2079}", Character("i"):"/u{2071}", Character("+"):"/u{207A}", Character("-"):"/u{207B}", Character("="):"/u{207C}", Character("("):"/u{207D}", Character(")"):"/u{207E}", Character("n"):"/u{207F}"] if let unicode = unicodeChars[self] { return unicode } return String(self) } } extension String { var unicodeSuperscript: String { let char = Character(self) return char.unicode } func superscripted() -> String { let regex = try! NSRegularExpression(pattern: "//^//{([^//}]*)//}") var unprocessedString = self var resultString = String() while let match = regex.firstMatch(in: unprocessedString, options: .reportCompletion, range: NSRange(location: 0, length: unprocessedString.count)) { // add substring before match let substringRange = unprocessedString.index(unprocessedString.startIndex, offsetBy: match.range.location) let subString = unprocessedString.prefix(upTo: substringRange) resultString.append(String(subString)) // add match with subscripted style let capturedSubstring = NSAttributedString(string: unprocessedString).attributedSubstring(from: match.range(at: 1)).mutableCopy() as! NSMutableAttributedString capturedSubstring.string.forEach { (char) in let superScript = char.unicode let string = NSAttributedString(string: superScript) resultString.append(string.string) } // strip off the processed part unprocessedString.deleteCharactersInRange(range: NSRange(location: 0, length: match.range.location + match.range.length)) } // add substring after last match resultString.append(unprocessedString) return resultString } mutating func deleteCharactersInRange(range: NSRange) { let mutableSelf = NSMutableString(string: self) mutableSelf.deleteCharacters(in: range) self = mutableSelf as String } }

Por ejemplo, "x^{4+n}+12^{3}".superscripted() produce "x⁴⁺ⁿ+12³"

Esto fue inspirado por HandyUIKit y la esencia de mi código está en Github


La mayoría de las respuestas + ejemplos están en ObjC, pero así es como hacerlo en Swift.

let font:UIFont? = UIFont(name: "Helvetica", size:20) let fontSuper:UIFont? = UIFont(name: "Helvetica", size:10) let attString:NSMutableAttributedString = NSMutableAttributedString(string: "6.022*1023", attributes: [.font:font!]) attString.setAttributes([.font:fontSuper!,.baselineOffset:10], range: NSRange(location:8,length:2)) labelVarName.attributedText = attString

Esto me da:

En una explicación más detallada:

  1. Obtenga UIFont que desee tanto para el estilo predeterminado como para el superíndice, el superíndice debe ser más pequeño.
  2. Cree un NSMutableAttributedString con la cadena completa y la fuente predeterminada.
  3. Agregue un atributo a los caracteres que desea cambiar ( NSRange ), con el UIFont más pequeño / subíndice, y el valor NSBaselineOffsetAttributeName es la cantidad que desea compensar verticalmente.
  4. Asignarlo a tu UILabel

Espero que esto ayude a otros desarrolladores de Swift, ya que también necesitaba esto.


Para una solución Swift fácil de usar , es posible que desee pagar HandyUIKit . Después de importarlo a su proyecto (por ejemplo, a través de Cartago, consulte las instrucciones en README) puede hacer algo como esto:

import HandyUIKit "6.022*10^{23}".superscripted(font: UIFont.systemFont(ofSize: 20, weight: .medium))

Esta línea devolverá un NSAttributedString que se verá exactamente como lo que está buscando . ¡Solo tiene que asignarlo a la propiedad attributedText UILabel y UILabel !

Si está buscando suscribir un texto, simplemente use subscripted(font:) lugar. Reconocerá estructuras como CO_{2} . También hay superAndSubscripted(font:) si quieres combinar ambos .

Consulte los docs para obtener más información y ejemplos adicionales.


Si puede llevarse bien con el texto que no se ve perfecto, y solo necesita un subconjunto de caracteres, puede utilizar los números de superíndice y subíndice Unicode: ⁰ ¹ ² ³ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ Esto tiene la ventaja de ser mucho menos engorroso.


Una función simple y agradable que genera un número como texto de superíndice.

func exponent(i: Int) -> String { let powers : [String] = [ "/u{2070}", "/u{00B9}", "/u{00B2}", "/u{00B3}", "/u{2074}", "/u{2075}", "/u{2076}", "/u{2077}", "/u{2078}", "/u{2079}" ] let digits = Array(String(i)) var string = "" for d in digits { string.append("/(powers[Int(String(d))!])") } return string }