1

I searched for the answer past days, and lot of them are very old (around swift 2 and 1.2). I wanted to get characters when unicode code is taken from the variable. Because for some unkown reason that consturction won't work in Swift:

print("\u{\(variable)}") // should be proposal for including this in Swift 6

people advice to use UnicodeScalars. However Apple must introduced something new in Swift 5. I found some tutorial here but this code fragment

let value0: UInt8 = 0x61
let value1: UInt16 = 0x5927
let value2: UInt32 = 0x1F34E

let string0 = String(UnicodeScalar(value0)) // a
let string1 = String(UnicodeScalar(value1)) // 大 error here
let string2 = String(UnicodeScalar(value2)) //  error here

is not working, with string1 and string2 I get error "no exact matches in call to initalizer". So as when author posted that I understand it must worked in previous version of Swift but with latest they do not. What is changed under the hood? Section for Strings in Apple handbook does not reveal anything.

I am trying to rewrite in Swift some code from Typescript and in JS is so simple like:

for (let i = str.length; i >= 1; i -= 2) {
        r = String.fromCharCode(parseInt("0x" + str.substring(i - 2, i))) + r;
    }

and I'm struggling with this for past 2 days without effect!

Sebastian
  • 448
  • 4
  • 14
  • If the actual purpose is to convert a hex-encoded string then this might be useful: https://stackoverflow.com/q/40276322/1187415 – Martin R Sep 06 '22 at 18:00

1 Answers1

2

The UnicodeScalar initializers taking an UInt16 or UInt32 argument are failable initializers (and return nil if the passed argument is an invalid Unicode scalar value).

public init?(_ v: UInt16)
public init?(_ v: UInt32)

The optional must be unwrapped before passing it to the String initializer.

Only the initializer taking an UInt8 argument is non-failable:

public init(_ v: UInt8)

So this compiles and produces the expected result:

let value0: UInt8 = 0x61
let value1: UInt16 = 0x5927
let value2: UInt32 = 0x1F34E

let string0 = String(UnicodeScalar(value0)) // a
let string1 = String(UnicodeScalar(value1)!) // 大
//                                        ^--- unwrap optional
let string2 = String(UnicodeScalar(value2)!) // 
//                                        ^--- unwrap optional

Of course, in your real code, you would use optional binding and not forced unwrapping.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382