20

I want to write a Unicode string using hexadecimal values in Swift. I have read the documentation for String and Character so I know that I can use special Unicode characters directly in strings like the following:

var variableString = "Cat‼" // "Cat" + Double Exclamation + cat emoji

But I would like to do it using the Unicode code points. The docs (and this question) show it for characters, but are not very clear about how to do it for strings.

(Note: Although the answer seems obvious to me now, it wasn't obvious at all just a short time ago. I am answering my own question below as a means of learning how to do this and also to help myself understand Unicode terminology and how Swift Characters and Strings work.)

Community
  • 1
  • 1
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393

2 Answers2

38

Character

The Swift syntax for forming a hexadecimal code point is

\u{n}

where n is a hexadecimal number up to 8 digits long. The valid range for a Unicode scalar is U+0 to U+D7FF and U+E000 to U+10FFFF inclusive. (The U+D800 to U+DFFF range is for surrogate pairs, which are not scalars themselves, but are used in UTF-16 for encoding the higher value scalars.)

Examples:

// The following forms are equivalent. They all produce "C". 
let char1: Character = "\u{43}"
let char2: Character = "\u{0043}"
let char3: Character = "\u{00000043}"

// Higher value Unicode scalars are done similarly
let char4: Character = "\u{203C}" // ‼ (DOUBLE EXCLAMATION MARK character)
let char5: Character = "\u{1F431}" //  (cat emoji)

// Characters can be made up of multiple scalars
let char7: Character = "\u{65}\u{301}" // é = "e" + accent mark
let char8: Character = "\u{65}\u{301}\u{20DD}" // é⃝ = "e" + accent mark + circle

Notes:

String

Strings are composed of characters. See the following examples for some ways to form them using hexadecimal code points.

Examples:

var string1 = "\u{0043}\u{0061}\u{0074}\u{203C}\u{1F431}" // Cat‼

// pass an array of characters to a String initializer
let catCharacters: [Character] = ["\u{0043}", "\u{0061}", "\u{0074}", "\u{203C}", "\u{1F431}"] // ["C", "a", "t", "‼", ""]
let string2 = String(catCharacters) // Cat‼

Converting Hex Values at Runtime

At runtime you can convert hexadecimal or Int values into a Character or String by first converting it to a UnicodeScalar.

Examples:

// hex values
let value0: UInt8  = 0x43     // 67
let value1: UInt16 = 0x203C   // 8252
let value2: UInt32 = 0x1F431  // 128049

// convert hex to UnicodeScalar
let scalar0 = UnicodeScalar(value0)
// make sure that UInt16 and UInt32 form valid Unicode values
guard
    let scalar1 = UnicodeScalar(value1),
    let scalar2 = UnicodeScalar(value2) else {
    return
}

// convert to Character
let character0 = Character(scalar0) // C
let character1 = Character(scalar1) // ‼
let character2 = Character(scalar2) // 

// convert to String
let string0 = String(scalar0) // C
let string1 = String(scalar1) // ‼
let string2 = String(scalar2) // 

// convert hex array to String
let myHexArray = [0x43, 0x61, 0x74, 0x203C, 0x1F431] // an Int array
var myString = ""
for hexValue in myHexArray {
    if let scalar = UnicodeScalar(hexValue) {
        myString.append(Character(scalar))
    }
}
print(myString) // Cat‼

Further reading

Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
  • @Suragch I have a unicode character `\u{0D85}`. How do I get the Int value from it? – Isuru Aug 03 '16 at 13:27
  • @Isuru, I have re-asked and answered your question here: [How to convert Unicode Character to Int in Swift](http://stackoverflow.com/questions/38779114/how-to-convert-unicode-character-to-int-in-swift) – Suragch Aug 04 '16 at 23:54
  • @Suragch Thanks so much for the detailed answer. I actually found how to do it in this [answer](http://stackoverflow.com/a/24102584/1077789). But still, good to have a thorough explanation. – Isuru Aug 05 '16 at 11:24
  • @Isuru, Just realize that in the answer you linked to, in the off chance that a `Character` is composed of more than one scalar, only the first scalar value will be returned. Any others will be ignored. (example: `let myChar: Character = "\u{65}\u{301}" // é`) – Suragch Aug 05 '16 at 14:20
  • how to combine hexadecimal number up to 8 digits long with \u{xxxx}? Hex number is an dynamic – karthikeyan Nov 13 '19 at 10:53
  • I am getting hexa decimal number from server like "ef29", I want to append that value into string like "\u{ef29}".. I am not able to do that... – karthikeyan Nov 15 '19 at 05:08
  • @karthikeyan, see [this](https://stackoverflow.com/questions/28401010/hex-string-to-character-in-pure-swift) – Suragch Nov 15 '19 at 05:43
  • Shouldn't this `let value = String(decoding: data, as: UTF8.self)` l do the job? – fullmoon Nov 09 '21 at 06:30
  • You cannot get UnicodeScalars from let value1: UInt16 = 0x203C // 22823 let value2: UInt32 = 0x1F431. Xcode is showing error – Sebastian Sep 06 '22 at 18:41
  • Also, return in guard is only allowed in function so the code above is not valid – Sebastian Sep 06 '22 at 18:43
  • in what universe 43 hexadecimal is 97? – Sebastian Sep 06 '22 at 19:36
  • @Sebastian, Apparently whatever universe my brain was in when I wrote that. Thanks for the comment. Conversions are fixed for this universe now. – Suragch Sep 13 '22 at 08:00
3

from your Hex "0x1F52D" to actual Emoji

let c = 0x1F602

next step would possibly getting an Uint32 from your Hex

let intEmoji = UnicodeScalar(c!).value

from this you can do something like

titleLabel.text = String(UnicodeScalar(intEmoji)!)

here you have a ""

it work with range of hexadecimal too

let emojiRanges = [
            0x1F600...0x1F636,
            0x1F645...0x1F64F,
            0x1F910...0x1F91F,
            0x1F30D...0x1F52D
        ]

        for range in emojiRanges {
            for i in range {
                let c = UnicodeScalar(i)!.value
                data.append(c)
            }
        }

to get multiple UInt32 from your Hex range for exemple

Mehdi S.
  • 471
  • 1
  • 4
  • 18
  • Please do not post the same answer to multiple questions. If the same information really answers both questions, then one question (usually the newer one) should be closed as a duplicate of the other. You can indicate this by [voting to close it as a duplicate](http://stackoverflow.com/help/privileges/close-questions) or, if you don't have enough reputation for that, [raise a flag](http://stackoverflow.com/help/privileges/flag-posts) to indicate that it's a duplicate. Otherwise, be sure you tailor your answer to *this* question and don't just paste the same answer in multiple places. – elixenide Dec 01 '17 at 02:35
  • Made this Medium Article that explain how it works https://medium.com/@kamiFR/how-to-show-emojis-with-strings-in-swift-using-unicode-hexadecimal-values-5093448cd1a9 – Mehdi S. Jun 01 '21 at 16:02
  • often same response apply to many questions and I support when author does this – Sebastian Sep 06 '22 at 18:44