2015-07-07 16 views
36

Nếu bạn không quan tâm đến các chi tiết của tiếng Mông Cổ nhưng chỉ muốn có câu trả lời nhanh về cách sử dụng và chuyển đổi các giá trị Unicode trong Swift, sau đó chuyển xuống phần đầu tiên của accepted answer.Làm việc với các điểm mã Unicode trong Swift


nền

Tôi muốn làm cho văn bản Unicode cho traditional Mongolian to be used in iOS apps. Giải pháp tốt hơn và dài hạn là sử dụng AAT smart font để hiển thị tập lệnh phức tạp này. (Such fonts do exist nhưng giấy phép của họ không cho phép sửa đổi và sử dụng phi cá nhân.) Tuy nhiên, vì tôi chưa bao giờ tạo phông chữ, hãy để một mình tất cả logic hiển thị cho phông chữ AAT, tôi chỉ định tự dựng hình trong Swift bây giờ . Có lẽ vào một số ngày sau đó tôi có thể học cách tạo ra một phông chữ thông minh.

Bên ngoài tôi sẽ sử dụng văn bản Unicode, nhưng bên trong (để hiển thị trong UITextView) tôi sẽ chuyển đổi Unicode thành từng ký tự được lưu trữ bằng phông chữ câm (được mã hóa với giá trị Unicode PUA). Vì vậy, công cụ dựng hình của tôi cần chuyển đổi các giá trị Unicode Mông Cổ (phạm vi: U + 1820 thành U + 1842) thành các giá trị glyph được lưu trữ trong PUA (phạm vi: U + E360 đến U + E5CF). Dù sao, đây là kế hoạch của tôi vì nó là what I did in Java in the past, nhưng có lẽ tôi cần phải thay đổi toàn bộ cách suy nghĩ của mình.

Ví dụ

Những hình ảnh dưới đây cho thấy su viết hai lần trong việc sử dụng hai hình thức khác nhau Mông Cổ cho chữ u (màu đỏ). (Mông Cổ được viết theo chiều dọc với chữ đang được kết nối như chữ cái chữ thảo bằng tiếng Anh.)

enter image description here

Trong Unicode hai chuỗi này sẽ được thể hiện dưới dạng

var suForm1: String = "\u{1830}\u{1826}" 
var suForm2: String = "\u{1830}\u{1826}\u{180B}" 

The Free Bộ chọn Biến (U + 180B) trong suForm2 được Swift String nhận dạng (chính xác) là đơn vị có u (U + 1826) đứng trước nó. Nó được Swift coi là một ký tự đơn, một cụm grapheme mở rộng. Tuy nhiên, với mục đích tự vẽ, tôi cần phân biệt u (U + 1826) và FVS1 (U + 180B) làm hai điểm mã UTF-16 riêng biệt.

Đối với mục đích hiển thị nội bộ, tôi sẽ chuyển đổi các chuỗi Unicode trên để các dây glyph rendered sau:

suForm1 = "\u{E46F}\u{E3BA}" 
suForm2 = "\u{E46F}\u{E3BB}" 

Câu hỏi

Tôi đã được chơi đùa với Swift StringCharacter. Có rất nhiều điều thuận tiện về chúng, nhưng vì trong trường hợp cụ thể của tôi, tôi xử lý riêng với các đơn vị mã UTF-16, tôi tự hỏi liệu tôi có nên sử dụng cũ NSString thay vì Swift của String. Tôi nhận thấy rằng tôi có thể sử dụng String.utf16 để nhận điểm mã UTF-16, nhưng the conversion back to String isn't very nice.

Bạn có nên gắn bó với StringCharacter hoặc tôi nên sử dụng NSStringunichar?

Những gì tôi đã đọc

cập nhật cho câu hỏi này đã được ẩn để làm sạch trang lên. Xem lịch sử chỉnh sửa.

+1

Câu hỏi của bạn không rõ ràng với tôi. 'count (string)' cung cấp số lượng "các cụm đồ thị unicode mở rộng", 'count (string.utf16)' cho số lượng các điểm mã UTF-16 được yêu cầu cho cùng một chuỗi (đó là độ dài của 'NSString' tương ứng. hoặc 'CFString'). (Và 'count (string.utf8)' sẽ cho biết số điểm mã UTF-8). - Câu hỏi * "Tôi có nên làm một cái gì đó như suForm1.utf16 mỗi khi tôi tham khảo một String?" * Không thể được trả lời nói chung, nó phụ thuộc vào những gì bạn cần đếm cho. –

+0

Tôi cần làm việc độc quyền (tôi nghĩ) với các điểm mã UTF-16. Đếm chiều dài của một chuỗi (trong UTF-16) là một điều tôi sẽ cần phải làm, nhưng nó chỉ là một ví dụ. Tôi cũng sẽ cần phải làm những việc như so sánh các ký tự (đó là các điểm mã UTF-16, không chỉ các cụm grapheme mà Swift xem xét bằng nhau). Tôi có nên sử dụng 'Chuỗi' hoặc' NSString' hay cái gì khác không? – Suragch

+0

Ý của bạn là gì theo "độ dài" ... Số byte? Đơn vị mã? Mã điểm? Cụm đồ thị? Điểm ảnh? Và tương tự cho "so sánh" ... Mã điểm bình đẳng? Tương đương Canonical? Tương thích tương thích? –

Trả lời

48

Cập nhật cho Swift 3

String và nhân vật

Đối với hầu hết mọi người trong tương lai ai truy cập vào câu hỏi này, String and Character sẽ là câu trả lời cho bạn.

giá trị Set Unicode trực tiếp trong mã:

var str: String = "I want to visit 北京, Москва, मुंबई, القاهرة, and 서울시. " 
var character: Character = "" 

Sử dụng hệ thập lục phân để thiết lập giá trị

var str: String = "\u{61}\u{5927}\u{1F34E}\u{3C0}" // a大π 
var character: Character = "\u{65}\u{301}" // é = "e" + accent mark 

Lưu ý rằng các nhân vật Swift có thể bao gồm nhiều điểm mã Unicode, nhưng xuất hiện là một nhân vật duy nhất. Đây được gọi là Cluster Grapheme mở rộng.

Xem this question.

Chuyển đổi sang giá trị Unicode:

str.utf8 
str.utf16 
str.unicodeScalars // UTF-32 

String(character).utf8 
String(character).utf16 
String(character).unicodeScalars 

Chuyển đổi từ giá trị hex Unicode:

let hexValue: UInt32 = 0x1F34E 

// convert hex value to UnicodeScalar 
guard let scalarValue = UnicodeScalar(hexValue) else { 
    // early exit if hex does not form a valid unicode value 
    return 
} 

// convert UnicodeScalar to String 
let myString = String(scalarValue) // 

Hoặc cách khác:

let hexValue: UInt32 = 0x1F34E 
if let scalarValue = UnicodeScalar(hexValue) { 
    let myString = String(scalarValue) 
} 

Một vài ví dụ khác

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

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

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

Lưu ý rằng đối với UTF-8 và UTF-16 việc chuyển đổi không phải lúc nào cũng dễ dàng như vậy. (Xem UTF-8, UTF-16, và UTF-32 câu hỏi.)

NSString và unichar

Nó cũng có thể làm việc với NSStringunichar trong Swift, nhưng bạn nên nhận ra rằng trừ khi bạn đã quen thuộc với C Mục tiêu và giỏi chuyển đổi cú pháp thành Swift, rất khó để tìm tài liệu tốt.

Ngoài ra, unichar là một mảng UInt16 và như đã đề cập ở trên việc chuyển đổi từ UInt16 các giá trị vô hướng Unicode không phải lúc nào cũng dễ dàng (ví dụ, chuyển đổi cặp thay thế cho những thứ như biểu tượng cảm xúc và các nhân vật khác trong những chiếc máy bay đang trên).

cấu trúc chuỗi tùy chỉnh

Đối với những lý do nêu trong câu hỏi, tôi đã kết thúc không sử dụng bất kỳ các phương pháp trên. Thay vào đó tôi đã viết cấu trúc chuỗi của riêng mình, về cơ bản là một mảng của UInt32 để giữ các giá trị vô hướng mã Unicode.

Một lần nữa, đây không phải là giải pháp cho hầu hết mọi người. Trước tiên, hãy cân nhắc sử dụng extensions nếu bạn chỉ cần mở rộng chức năng của String hoặc Character một chút.

Nhưng nếu bạn thực sự cần làm việc độc quyền với các giá trị vô hướng Unicode, bạn có thể viết cấu trúc tùy chỉnh.

Những lợi thế là:

  • Bạn không cần phải liên tục chuyển đổi giữa các loại (String, Character, UnicodeScalar, UInt32, vv) khi thực hiện chuỗi thao tác.
  • Sau khi thao tác Unicode hoàn tất, chuyển đổi cuối cùng thành String thật dễ dàng.
  • Dễ dàng thêm các phương pháp hơn khi họ là cần thiết
  • đơn giản hoá chuyển đổi mã từ Java hoặc các ngôn ngữ khác

Disadavantages là:

  • làm cho mã ít di động và ít có thể đọc cho các nhà phát triển Swift khác
  • không được kiểm tra và tối ưu hóa tốt như các loại Swift gốc
  • đó là một tệp khác phải được bao gồm trong dự án mỗi khi bạn cần nó

Bạn có thể tự tạo, nhưng đây là tài liệu tham khảo của tôi. Phần khó nhất là making it Hashable.

// This struct is an array of UInt32 to hold Unicode scalar values 
// Version 3.4.0 (Swift 3 update) 


struct ScalarString: Sequence, Hashable, CustomStringConvertible { 

    fileprivate var scalarArray: [UInt32] = [] 


    init() { 
     // does anything need to go here? 
    } 

    init(_ character: UInt32) { 
     self.scalarArray.append(character) 
    } 

    init(_ charArray: [UInt32]) { 
     for c in charArray { 
      self.scalarArray.append(c) 
     } 
    } 

    init(_ string: String) { 

     for s in string.unicodeScalars { 
      self.scalarArray.append(s.value) 
     } 
    } 

    // Generator in order to conform to SequenceType protocol 
    // (to allow users to iterate as in `for myScalarValue in myScalarString` { ... }) 
    func makeIterator() -> AnyIterator<UInt32> { 
     return AnyIterator(scalarArray.makeIterator()) 
    } 

    // append 
    mutating func append(_ scalar: UInt32) { 
     self.scalarArray.append(scalar) 
    } 

    mutating func append(_ scalarString: ScalarString) { 
     for scalar in scalarString { 
      self.scalarArray.append(scalar) 
     } 
    } 

    mutating func append(_ string: String) { 
     for s in string.unicodeScalars { 
      self.scalarArray.append(s.value) 
     } 
    } 

    // charAt 
    func charAt(_ index: Int) -> UInt32 { 
     return self.scalarArray[index] 
    } 

    // clear 
    mutating func clear() { 
     self.scalarArray.removeAll(keepingCapacity: true) 
    } 

    // contains 
    func contains(_ character: UInt32) -> Bool { 
     for scalar in self.scalarArray { 
      if scalar == character { 
       return true 
      } 
     } 
     return false 
    } 

    // description (to implement Printable protocol) 
    var description: String { 
     return self.toString() 
    } 

    // endsWith 
    func endsWith() -> UInt32? { 
     return self.scalarArray.last 
    } 

    // indexOf 
    // returns first index of scalar string match 
    func indexOf(_ string: ScalarString) -> Int? { 

     if scalarArray.count < string.length { 
      return nil 
     } 

     for i in 0...(scalarArray.count - string.length) { 

      for j in 0..<string.length { 

       if string.charAt(j) != scalarArray[i + j] { 
        break // substring mismatch 
       } 
       if j == string.length - 1 { 
        return i 
       } 
      } 
     } 

     return nil 
    } 

    // insert 
    mutating func insert(_ scalar: UInt32, atIndex index: Int) { 
     self.scalarArray.insert(scalar, at: index) 
    } 
    mutating func insert(_ string: ScalarString, atIndex index: Int) { 
     var newIndex = index 
     for scalar in string { 
      self.scalarArray.insert(scalar, at: newIndex) 
      newIndex += 1 
     } 
    } 
    mutating func insert(_ string: String, atIndex index: Int) { 
     var newIndex = index 
     for scalar in string.unicodeScalars { 
      self.scalarArray.insert(scalar.value, at: newIndex) 
      newIndex += 1 
     } 
    } 

    // isEmpty 
    var isEmpty: Bool { 
     return self.scalarArray.count == 0 
    } 

    // hashValue (to implement Hashable protocol) 
    var hashValue: Int { 

     // DJB Hash Function 
     return self.scalarArray.reduce(5381) { 
      ($0 << 5) &+ $0 &+ Int($1) 
     } 
    } 

    // length 
    var length: Int { 
     return self.scalarArray.count 
    } 

    // remove character 
    mutating func removeCharAt(_ index: Int) { 
     self.scalarArray.remove(at: index) 
    } 
    func removingAllInstancesOfChar(_ character: UInt32) -> ScalarString { 

     var returnString = ScalarString() 

     for scalar in self.scalarArray { 
      if scalar != character { 
       returnString.append(scalar) 
      } 
     } 

     return returnString 
    } 
    func removeRange(_ range: CountableRange<Int>) -> ScalarString? { 

     if range.lowerBound < 0 || range.upperBound > scalarArray.count { 
      return nil 
     } 

     var returnString = ScalarString() 

     for i in 0..<scalarArray.count { 
      if i < range.lowerBound || i >= range.upperBound { 
       returnString.append(scalarArray[i]) 
      } 
     } 

     return returnString 
    } 


    // replace 
    func replace(_ character: UInt32, withChar replacementChar: UInt32) -> ScalarString { 

     var returnString = ScalarString() 

     for scalar in self.scalarArray { 
      if scalar == character { 
       returnString.append(replacementChar) 
      } else { 
       returnString.append(scalar) 
      } 
     } 
     return returnString 
    } 
    func replace(_ character: UInt32, withString replacementString: String) -> ScalarString { 

     var returnString = ScalarString() 

     for scalar in self.scalarArray { 
      if scalar == character { 
       returnString.append(replacementString) 
      } else { 
       returnString.append(scalar) 
      } 
     } 
     return returnString 
    } 
    func replaceRange(_ range: CountableRange<Int>, withString replacementString: ScalarString) -> ScalarString { 

     var returnString = ScalarString() 

     for i in 0..<scalarArray.count { 
      if i < range.lowerBound || i >= range.upperBound { 
       returnString.append(scalarArray[i]) 
      } else if i == range.lowerBound { 
       returnString.append(replacementString) 
      } 
     } 
     return returnString 
    } 

    // set (an alternative to myScalarString = "some string") 
    mutating func set(_ string: String) { 
     self.scalarArray.removeAll(keepingCapacity: false) 
     for s in string.unicodeScalars { 
      self.scalarArray.append(s.value) 
     } 
    } 

    // split 
    func split(atChar splitChar: UInt32) -> [ScalarString] { 
     var partsArray: [ScalarString] = [] 
     if self.scalarArray.count == 0 { 
      return partsArray 
     } 
     var part: ScalarString = ScalarString() 
     for scalar in self.scalarArray { 
      if scalar == splitChar { 
       partsArray.append(part) 
       part = ScalarString() 
      } else { 
       part.append(scalar) 
      } 
     } 
     partsArray.append(part) 
     return partsArray 
    } 

    // startsWith 
    func startsWith() -> UInt32? { 
     return self.scalarArray.first 
    } 

    // substring 
    func substring(_ startIndex: Int) -> ScalarString { 
     // from startIndex to end of string 
     var subArray: ScalarString = ScalarString() 
     for i in startIndex..<self.length { 
      subArray.append(self.scalarArray[i]) 
     } 
     return subArray 
    } 
    func substring(_ startIndex: Int, _ endIndex: Int) -> ScalarString { 
     // (startIndex is inclusive, endIndex is exclusive) 
     var subArray: ScalarString = ScalarString() 
     for i in startIndex..<endIndex { 
      subArray.append(self.scalarArray[i]) 
     } 
     return subArray 
    } 

    // toString 
    func toString() -> String { 
     var string: String = "" 

     for scalar in self.scalarArray { 
      if let validScalor = UnicodeScalar(scalar) { 
       string.append(Character(validScalor)) 
      } 
     } 
     return string 
    } 

    // trim 
    // removes leading and trailing whitespace (space, tab, newline) 
    func trim() -> ScalarString { 

     //var returnString = ScalarString() 
     let space: UInt32 = 0x00000020 
     let tab: UInt32 = 0x00000009 
     let newline: UInt32 = 0x0000000A 

     var startIndex = self.scalarArray.count 
     var endIndex = 0 

     // leading whitespace 
     for i in 0..<self.scalarArray.count { 
      if self.scalarArray[i] != space && 
       self.scalarArray[i] != tab && 
       self.scalarArray[i] != newline { 

       startIndex = i 
       break 
      } 
     } 

     // trailing whitespace 
     for i in stride(from: (self.scalarArray.count - 1), through: 0, by: -1) { 
      if self.scalarArray[i] != space && 
       self.scalarArray[i] != tab && 
       self.scalarArray[i] != newline { 

       endIndex = i + 1 
       break 
      } 
     } 

     if endIndex <= startIndex { 
      return ScalarString() 
     } 

     return self.substring(startIndex, endIndex) 
    } 

    // values 
    func values() -> [UInt32] { 
     return self.scalarArray 
    } 

} 

func ==(left: ScalarString, right: ScalarString) -> Bool { 
    return left.scalarArray == right.scalarArray 
} 

func +(left: ScalarString, right: ScalarString) -> ScalarString { 
    var returnString = ScalarString() 
    for scalar in left.values() { 
     returnString.append(scalar) 
    } 
    for scalar in right.values() { 
     returnString.append(scalar) 
    } 
    return returnString 
} 
0
//Swift 3.0 
// This struct is an array of UInt32 to hold Unicode scalar values 
struct ScalarString: Sequence, Hashable, CustomStringConvertible { 

    private var scalarArray: [UInt32] = [] 

    init() { 
     // does anything need to go here? 
    } 

    init(_ character: UInt32) { 
     self.scalarArray.append(character) 
    } 

    init(_ charArray: [UInt32]) { 
     for c in charArray { 
      self.scalarArray.append(c) 
     } 
    } 

    init(_ string: String) { 

     for s in string.unicodeScalars { 
      self.scalarArray.append(s.value) 
     } 
    } 

    // Generator in order to conform to SequenceType protocol 
    // (to allow users to iterate as in `for myScalarValue in myScalarString` { ... }) 

    //func generate() -> AnyIterator<UInt32> { 
    func makeIterator() -> AnyIterator<UInt32> { 

     let nextIndex = 0 

     return AnyIterator { 
      if (nextIndex > self.scalarArray.count-1) { 
       return nil 
      } 
      return self.scalarArray[nextIndex + 1] 
     } 
    } 

    // append 
    mutating func append(scalar: UInt32) { 
     self.scalarArray.append(scalar) 
    } 

    mutating func append(scalarString: ScalarString) { 
     for scalar in scalarString { 
      self.scalarArray.append(scalar) 
     } 
    } 

    mutating func append(string: String) { 
     for s in string.unicodeScalars { 
      self.scalarArray.append(s.value) 
     } 
    } 

    // charAt 
    func charAt(index: Int) -> UInt32 { 
     return self.scalarArray[index] 
    } 

    // clear 
    mutating func clear() { 
     self.scalarArray.removeAll(keepingCapacity: true) 
    } 

    // contains 
    func contains(character: UInt32) -> Bool { 
     for scalar in self.scalarArray { 
      if scalar == character { 
       return true 
      } 
     } 
     return false 
    } 

    // description (to implement Printable protocol) 
    var description: String { 

     var string: String = "" 

     for scalar in scalarArray { 
      string.append(String(describing: UnicodeScalar(scalar))) //.append(UnicodeScalar(scalar)!) 
     } 
     return string 
    } 

    // endsWith 
    func endsWith() -> UInt32? { 
     return self.scalarArray.last 
    } 

    // insert 
    mutating func insert(scalar: UInt32, atIndex index: Int) { 
     self.scalarArray.insert(scalar, at: index) 
    } 

    // isEmpty 
    var isEmpty: Bool { 
     get { 
      return self.scalarArray.count == 0 
     } 
    } 

    // hashValue (to implement Hashable protocol) 
    var hashValue: Int { 
     get { 

      // DJB Hash Function 
      var hash = 5381 

      for i in 0 ..< scalarArray.count { 
       hash = ((hash << 5) &+ hash) &+ Int(self.scalarArray[i]) 
      } 
      /* 
      for i in 0..< self.scalarArray.count { 
      hash = ((hash << 5) &+ hash) &+ Int(self.scalarArray[i]) 
      } 
      */ 
      return hash 
     } 
    } 

    // length 
    var length: Int { 
     get { 
      return self.scalarArray.count 
     } 
    } 

    // remove character 
    mutating func removeCharAt(index: Int) { 
     self.scalarArray.remove(at: index) 
    } 
    func removingAllInstancesOfChar(character: UInt32) -> ScalarString { 

     var returnString = ScalarString() 

     for scalar in self.scalarArray { 
      if scalar != character { 
       returnString.append(scalar: scalar) //.append(scalar) 
      } 
     } 

     return returnString 
    } 

    // replace 
    func replace(character: UInt32, withChar replacementChar: UInt32) -> ScalarString { 

     var returnString = ScalarString() 

     for scalar in self.scalarArray { 
      if scalar == character { 
       returnString.append(scalar: replacementChar) //.append(replacementChar) 
      } else { 
       returnString.append(scalar: scalar) //.append(scalar) 
      } 
     } 
     return returnString 
    } 

    // func replace(character: UInt32, withString replacementString: String) -> ScalarString { 
    func replace(character: UInt32, withString replacementString: ScalarString) -> ScalarString { 

     var returnString = ScalarString() 

     for scalar in self.scalarArray { 
      if scalar == character { 
       returnString.append(scalarString: replacementString) //.append(replacementString) 
      } else { 
       returnString.append(scalar: scalar) //.append(scalar) 
      } 
     } 
     return returnString 
    } 

    // set (an alternative to myScalarString = "some string") 
    mutating func set(string: String) { 
     self.scalarArray.removeAll(keepingCapacity: false) 
     for s in string.unicodeScalars { 
      self.scalarArray.append(s.value) 
     } 
    } 

    // split 
    func split(atChar splitChar: UInt32) -> [ScalarString] { 
     var partsArray: [ScalarString] = [] 
     var part: ScalarString = ScalarString() 
     for scalar in self.scalarArray { 
      if scalar == splitChar { 
       partsArray.append(part) 
       part = ScalarString() 
      } else { 
       part.append(scalar: scalar) //.append(scalar) 
      } 
     } 
     partsArray.append(part) 
     return partsArray 
    } 

    // startsWith 
    func startsWith() -> UInt32? { 
     return self.scalarArray.first 
    } 

    // substring 
    func substring(startIndex: Int) -> ScalarString { 
     // from startIndex to end of string 
     var subArray: ScalarString = ScalarString() 
     for i in startIndex ..< self.length { 
      subArray.append(scalar: self.scalarArray[i]) //.append(self.scalarArray[i]) 
     } 
     return subArray 
    } 
    func substring(startIndex: Int, _ endIndex: Int) -> ScalarString { 
     // (startIndex is inclusive, endIndex is exclusive) 
     var subArray: ScalarString = ScalarString() 
     for i in startIndex ..< endIndex { 
      subArray.append(scalar: self.scalarArray[i]) //.append(self.scalarArray[i]) 
     } 
     return subArray 
    } 

    // toString 
    func toString() -> String { 
     let string: String = "" 

     for scalar in self.scalarArray { 
      string.appending(String(describing:UnicodeScalar(scalar))) //.append(UnicodeScalar(scalar)!) 
     } 
     return string 
    } 

    // values 
    func values() -> [UInt32] { 
     return self.scalarArray 
    } 

} 

func ==(left: ScalarString, right: ScalarString) -> Bool { 

    if left.length != right.length { 
     return false 
    } 

    for i in 0 ..< left.length { 
     if left.charAt(index: i) != right.charAt(index: i) { 
      return false 
     } 
    } 

    return true 
} 

func +(left: ScalarString, right: ScalarString) -> ScalarString { 
    var returnString = ScalarString() 
    for scalar in left.values() { 
     returnString.append(scalar: scalar) //.append(scalar) 
    } 
    for scalar in right.values() { 
     returnString.append(scalar: scalar) //.append(scalar) 
    } 
    return returnString 
} 
+0

Tôi nghĩ rằng bằng cách sử dụng 'String (mô tả: UnicodeScalar (vô hướng))' sản xuất Strings với "Tùy chọn" được viết trong chúng.Xem cập nhật cho câu trả lời của tôi cho một phương pháp tốt hơn. – Suragch

Các vấn đề liên quan