I want my UILabel
to display text in following manner 6.022*1023. What functions does Swift have for subscript and superscript?

- 9,600
- 4
- 39
- 43

- 1,321
- 4
- 20
- 36
-
See http://stackoverflow.com/questions/8555735/how-to-make-subscripts-and-superscripts-using-nsattributedstring. – Martin R Mar 24 '15 at 06:23
20 Answers
Most of the answers+examples are in ObjC, but this is how to do it in 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
This gives me:
In a more detailed explanation:
- Get
UIFont
you want for both the default and superscript style, superscript must be smaller. - Create a
NSMutableAttributedString
with the full string and default font. - Add an attribute to the characters you want to change (
NSRange
), with the smaller/subscriptUIFont
, and theNSBaselineOffsetAttributeName
value is the amount you want to offset it vertically. - Assign it to your
UILabel
Hopefully this helps other Swift devs as I needed this as well.

- 11,454
- 9
- 54
- 64

- 1,392
- 1
- 10
- 11
-
1This crashes if Helvetica isn't available in point sizes 10 or 20. Even sample code should be written with a modicum of error handling. Also the variable names make it confusing, and it doesn't compile. – SafeFastExpressive Feb 03 '18 at 00:35
As a different approach, I wrote a function that takes in a string where the exponents are prepended with ^
such as 2^2•3•5^2
and returns 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
}
It's a bit of a brute force method, but it works if you don't want to deal with attributed strings or you want your string to be independent of a font.

- 7,270
- 19
- 66
- 110
If you can get along with text that doesn't look perfect, and only need a subset of characters you can make use of the unicode superscript and subscript numbers: ⁰ ¹ ² ³ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ This has the advantage of being a lot less cumbersome.

- 5,447
- 2
- 25
- 29
-
Another advantage of this is that when you have multiple lines, this does not mess with the linespacing as the shifting the baseline in the attributed string does. – Carien van Zyl Mar 01 '18 at 11:18
I wrote the following extension or you can use it as a function, it is working well for me . you can modify it by skipping the parts that are not essential to you
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}
}
examples:
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)

- 547
- 4
- 7
-
1Very nice. I extended it a little by adding a `textColor` parameter. And replaced the `UIFont.boldSystemFont` with `UIFont.systemFont`. – Isuru Mar 29 '17 at 06:35
-
My solution as an extension of String
extension String {
func setAsSuperscript(_ textToSuperscript: String) -> NSMutableAttributedString {
let attributedString = NSMutableAttributedString(string: self)
let foundRange = attributedString.mutableString.range(of: textToSuperscript)
let font = UIFont.systemFont(ofSize: 12)
if foundRange.location != NSNotFound {
attributedString.addAttribute(.font, value: font, range: foundRange)
attributedString.addAttribute(.baselineOffset, value: 3, range: foundRange)
attributedString.addAttribute(.foregroundColor, value: UIColor.red, range: foundRange)
}
return attributedString
}
And usage:
let placeholder = "Required value*".setAsSuperscript("*")
myLabel.attributedText = placeholder
-
This is the correct answer. All these other answers with static numeric values and which are unnecessarily long will fail you in a tech interview. – zeeshan Nov 23 '22 at 14:21
For a simple to use Swift solution, you might want to checkout HandyUIKit. After importing it into your project (e.g. via Carthage – see instructions in README) you can do something like this:
import HandyUIKit
"6.022*10^{23}".superscripted(font: UIFont.systemFont(ofSize: 20, weight: .medium))
This line will return an NSAttributedString
which will look exactly like what you're looking for. Just assign it to a UILabel
s attributedText
property and that's it!
If you're looking for subscripting a text, simply use subscripted(font:)
instead. It will recognize structures like CO_{2}
. There's also superAndSubscripted(font:)
if you want to combine both.
See the docs for more information and additional examples.

- 20,202
- 8
- 59
- 80
Here is a simple version that has correct error handling and will compile in playground.
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)

- 3,637
- 2
- 32
- 39
Swift 4+ Version of @Atka's Answer
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
}
}

- 1
- 1

- 3,497
- 6
- 30
- 69
Here's a Swift 5.1 solution (should work with older versions of Swift too) using recursion, that only focuses outputting a superscript from an Int
(i.e. no formatting for display).
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]
}
}
Here are some tests to prove correctness:
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(), "⁻¹³³⁷")
}
My solution is more than twice as fast as gorillaz' solution(which is string and array based), thanks to mine being math and recursion based. Here is proof:
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 testPerformanceStackOverflow() {
measure {
performanceTest(times: 1_000_000, function: Int.superscriptStringArrayBased)
}
}

- 8,938
- 5
- 60
- 94
-
`assert(int >= 0 && int <= 9)` would be better expressed as `assert((0...9).contains(int))`, or even better as `assert(values.indices.contains(int))`. But there's no point to doing that if you don't also include a helpful user message, because it wouldn't provide any value over the array subscript's usual crash-on-out-of-bounds behaviour. – Alexander Oct 22 '19 at 16:29
For those using SwiftUI, an option is to use a unicode exception string in Text():
Text("c\u{2082}=a\u{2082}+b\u{2082}") /// c^2 = a^2 + b^2
One benefit of this method is easier inline subs/supers.
If it must absolutely inherit from UILabel (e.g. for native NSAttributedString or native wrapping), you can leverage UIViewRepresentable and use the unicode exception string (which should work in most cases). Here is an option on SO: Stackoverflow. I have not tried the answer.
And for those looking for unicode for common subscripts and superscripts (e.g. for arithmetic):
Superscripts:
0 = 2070
1 = 00B9
2 = 00B2
3 = 00B3
4 = 2074
5 = 2075
6 = 2076
7 = 2077
8 = 2078
9 = 2079
+ = 207A
- = 207B
( = 207D
) = 207E
n = 207F
Subscripts:
0 = 2080
1 = 2081
2 = 2082
3 = 2083
4 = 2084
5 = 2085
6 = 2086
7 = 2087
8 = 2088
9 = 2089
+ = 208A
- = 208B
( = 208D
) = 208E
e = 2091
n = 2099
Reference: unicode.org

- 1
- 1

- 1,124
- 2
- 12
- 26
A nice simple function that outputs a number as the superscript text.
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
}

- 143
- 1
- 6
In SwiftUI it is possible to achieve superscript effect by using baselineOffset modifier. For example:
Text("$")
.foregroundColor(Color.white)
.font(.custom(AppTheme.getRegularFont(), size: 13))
.baselineOffset(8.0)
Text("20")
.foregroundColor(AppTheme.primaryColor)
.font(.custom(AppTheme.getRegularFont(), size: 25))
Here is how it looks:

- 675
- 9
- 14
I have created a String extension which takes a string and converts all of its superscript into unicode characters. This way you could for example share the resulting string without any hassle.
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
}
}
For example "x^{4+n}+12^{3}".superscripted()
produces "x⁴⁺ⁿ+12³"
This was inspired by HandyUIKit and the gist to my code is on Github

- 1,448
- 16
- 23
Here is what I came up with for a SwiftUI Text view with subscripts and superscripts embedded in the String initialize. Surround a subscript with \\b[text]\\e and a superscript with \\a[text]\\e where [text] are the characters in the sub- or superscript.
//
// FormattedText.swift
//
// Created by Joseph Levy on 8/25/21.
import Foundation
import SwiftUI
enum Attribute { case normal; case sub; case sup }
struct AttributedString {
var attribute: Attribute
var string: String
}
func StringToAttributedStrings(_ string: String) -> [AttributedString] {
//var lastAtt: Attribute = .normal
var splits = string.components(separatedBy: "\\")
var filter = false
var attSplits: [AttributedString] = []
for i in splits.indices {
var a: Attribute = { //() -> Attribute in
let firstchar = splits[i].first
switch firstchar {
case "a": do { a = .sup; filter = true }
case "b": do { a = .sub; filter = true }
case "e": do { a = .normal; filter = true }
default: do {
a = .normal
if i > 0 { splits[i] = "\\" + splits[i] }
filter = false;
}
}
return a
}()
attSplits.append(AttributedString(attribute: a, string: filter ? String(splits[i].dropFirst()) : splits[i] ))
}
return attSplits
}
func FormattedText(_ string: String, up: CGFloat = 8, down: CGFloat = 3) -> Text {
let aStrings = StringToAttributedStrings(string)
var returnText = Text("")
var addedText: Text
for aString in aStrings {
switch aString.attribute {
case .normal: addedText = Text(aString.string)
case .sub: addedText = Text(aString.string).font(.footnote).baselineOffset(-down)
case .sup: addedText = Text(aString.string).font(.footnote).baselineOffset(up)
}
returnText = returnText + addedText
}
return returnText
}
Use
FormattedText("Al\\bx\\eGa\\b1-x\\eAs\\a*\\e")
gives

- 157
- 8
I wrote a fun little algorithm for this as an extension on Int that doesn't require any messy attributed strings.
Usage:
let superscriptString = 8675309.superscriptString
Implementation:
extension Int {
var superscriptString: String {
var input: Int = self
var result: String = ""
while input > 0 {
let lastDigit = input % 10
input /= 10
guard let superscript = lastDigit.superscript else { continue }
result = superscript + result
}
return result
}
private var superscript: String? {
switch self {
case 0:
return "\u{2070}"
case 1:
return "\u{00B9}"
case 2:
return "\u{00B2}"
case 3:
return "\u{00B3}"
case 4:
return "\u{2074}"
case 5:
return "\u{2075}"
case 6:
return "\u{2076}"
case 7:
return "\u{2077}"
case 8:
return "\u{2078}"
case 9:
return "\u{2079}"
default:
return nil
}
}
}

- 2,965
- 4
- 25
- 52
I created an AmountFormatter class which helped me convert decimal numbers into numbers with raised decimals.
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
}
}
extension String {
func convertToSuperscriptDigits(from start: Int, to end: Int? = nil) - String {
let end = end ?? self.count
let startIndex = self.index(self.startIndex, offsetBy: start)
let endIndex = self.index(self.startIndex, offsetBy: end)
let replaceRange = startIndex..<endIndex
let substring = self[replaceRange]
let supers = [
"0": "\u{2070}",
"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}"]
let convertString = substring.map { (char) -> Character in
Character(supers[String(char)] ?? String(char))
}
return self.replacingCharacters(in: replaceRange, with: String(convertString))
}

- 61
- 3
-
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – Piotr Labunski Apr 07 '20 at 10:03
This will superscript all the numbers in a string and remove the ^ character.
Use:
yourstring.addSuper()
code:
extension String {
func addSuper() -> String {
let charset = CharacterSet(charactersIn: "1234567890")
let toSuper: [Character: String] = ["0": "\u{2070}",
"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}",
"-": "\u{207B}"]
var resultString: String = ""
var index: Int = 0
for charater in self {
if String(charater).rangeOfCharacter(from: charset) != nil {
resultString.append(toSuper[charater] ?? "")
} else if charater != "^" {
resultString.append(charater)
}
index += 1
}
return resultString
}
}

- 359
- 3
- 10
First an extension to get a substring
extension String {
subscript(idx: Int) -> String {
String(self[index(startIndex, offsetBy: idx)])
}
}
Next get the actual superScript
func superScript(_ num: Int) -> String {
var s = ""
let numStr = String(num)
for n in numStr.utf8 {
let i = Int(n) - 48 // utf8 for '0'
s += "⁰¹²³⁴⁵⁶⁷⁸⁹"[i]
}
return s
}
and to test
for i in 0...12 { print(superScript(i), terminator: " ") }
print(superScript(12345), terminator: " ")
yielding output
⁰ ¹ ² ³ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹ ¹⁰ ¹¹ ¹² ¹²³⁴⁵

- 1,692
- 1
- 17
- 14
in CoreText there is a key for such style: https://developer.apple.com/documentation/coretext/kctsuperscriptattributename
so NSAttributedString has undocumented key
__C.NSAttributedStringKey(_rawValue: NSSuperScript)
so few lines of code can do the job:
extension NSMutableAttributedString {
func applySuperscript(range: NSRange) {
let superScriptKey = NSAttributedString.Key("NSSuperScript")
addAttribute(superScriptKey, value: Int64(1) , range: range)
}
}
to make a subscript - use Int64(-1)
I didn't research when this key appeared, maybe it was exist since even iOS 3 sdk. Also, keep in mind there is no guarantee Apple won't modify this key in future.

- 2,237
- 1
- 13
- 9