 Apple Lover Developer & Artist

영속적인 디자인에 현대의 공감을 채워넣는 공방입니다

 Apple/Swift Programming Language

[Swift] 공식문서 씹어먹기: Strings and Characters

singularis7 2021. 9. 23. 22:54
반응형

Swift Logo

Overview

  • String은 "hello, world" 혹은 "albatross"와 같은 문자들의 나열 (문자열) 이다.
  • Swift에서의 문자열은 String type으로 사용된다.
  • String의 내부값은 문자값들의 컬렉션을 포함하여 다양한 방식으로 접근할 수 있다.

 

  • Swift의 String과 Character type은 코드에서 텍스트를 다룰 때 빠르고 유니코드 호환 방법을 제공한다.
  • String을 생성(creation)하고 수정(manipulation)하는 문법은 가볍고 가독성이 좋으며 C와 유사한 String literal 문법을 제공한다.
  • String Concatenation은 + 연산자를 사용하여 쉽게 두개의 String을 결합시켜준다.
  • String mutability는 Swift에서의 다른 값처럼 상수인지 변수인지에 따라 다르게 관리된다.
  • String interporation을 통해 어느 긴 String값에 상수, 변수, literal과 다른 표현식을 삽입시킬 수 있다.

 

  • Swift는 문법이 단순하지만 빠르고 현대적인 string type을 구현하고 있다.
  • 모든 String은 인코딩에 독립적인 Unicode 문자열로 구성되어있다.
  • 다양한 Unicode 표현을 갖는 String의 문자들에 접근할 수 있도록 한다.
Note
Swift의 String type은 Foundation의 NSString 클래스와 연결(bridged)되어있습니다. Foundation은 String을 NSString에 정의된 외부 메서드로 확장(extends)시키고 있습니다. 즉, Foundation을 import하면 casting을 사용하지 않고 String에서 NSString 메서드에 접근할 수 있다는 의미입니다.

Foundation과 Cocoa와 함께 사용되는 String에관한 자세한 정보를 얻고 싶다면 Bridging Between String and NSString 를 참조하세요.

String Literals

  • String literals를 활용하여 코드에 String 값을 사전에 정의할 수 있다.
  • String literal은 이중 인용 부호 " 를 문자열에 둘러쌓아 사용할 수 있다.
  • 상수나 변수의 초기값으로 String literal을 사용하는 예시는 다음과 같다.
let someString = "Some string literal value"
// Swift infers a type of String for the someString constant because it's initialized with a string literal value.

 

Multiline String Literals

  • 만약 여러줄에 걸쳐서 String을 쓰고 싶다면 multiline string literal """ 를 사용하는 방법이 있다.
let quotation = """
The White Rabbit put on his spectacles. "Where shall I begin, 
please your Majesty?" he asked.

"Begin at the beginning," the King said gravely, "and go on
till you come to the end; then stop."
"""
  • ''' 를 사용할 때 특정 명령어를 사용하지 않으면 줄바꿈(line break)이 동작하지않는다.
  • 줄바꿈(line break)을 표현하려면 백슬래시(backslash)를 사용하면 된다.
let softWrappedQuotation = """
The White Rabbit put on his spectacles.  "Where shall I begin, \
please your Majesty?" he asked.

"Begin at the beginning," the King said gravely, "and go on \
till you come to the end; then stop."
"""
  • multiline string literal을 사용할 때에는 첫번째 줄과 마지막 줄을 공백으로 작성하는 것이 좋다.
let lineBreaks = """

This string starts with a line break.
It also ends with a line break.

"""
  • multiline string은 주변 코드와 일치하도록 들여쓰기(indented)될 수 있다.
  • 닫히는 부분의 """ 앞에 있는 공백은 모든 줄에 있어서 무시해야 하는 공백을 의미한다.
  • 닫는 따옴표 앞에 있는 공백의 경우 해당 공백이 String에 포함된다.

 

Special Characters in String Literals

  • String literal은 다음과 같은 특수 기호를 포함한다.
  • \0 : null characte, 널 문자
  • \\ : backslash, 백슬래시
  • \t : horizontal tab, 가로 탭
  • \r : carriage return, 커서의 위치를 줄의 맨 처음으로 보내줌
  • \" : 문자열 내부에서 따옴표 사용
  • \' : 문자열 내부에서 작은 따옴표 사용
  • \u{n} : 유니코드 문자 입력, n에는 1~8자리의 16진수를 입력
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
// "Imagination is more important than knowledge" - Einstein
let dollarSign = "\u{24}"        // $,  Unicode scalar U+0024
let blackHeart = "\u{2665}"      // ♥,  Unicode scalar U+2665
let sparklingHeart = "\u{1F496}" // 💖, Unicode scalar U+1F496
  • multiline string literal에서도 escape 문자를 활용할 수 있다.
let threeDoubleQuotationMarks = """
Escaping the first quotation mark \"""
Escaping all three quotation marks \"\"\"
"""

 

Extended String Delimiters

  • 확장된 구분문자 내부에 string literal을 두어서 특수 문자의 효과 없이 문자열로 표현할 수 있다.
  • 따옴표 " 내부에 문자열을 넣고 숫자기호 # 으로 감싸준다.
let text1 = #"Line 1 \n Line 2"#         // Line 1 \nLine 2
let text2 = #"Line 1 \#n Line 2"#        // Line 1 개행 Line 2
let text3 = ###"Line 1 \###n Line 2"###  // Line 1 개행 Line 2
  • multiline string literal에서도 확장 구분 문자를 동일하게 사용할 수 있다.
let threeMoreDoubleQuotationMarks = #"""
Here are three more double quotes: """
"""#

Initializing an Empty String

  • 변수에 비어있는 string literal을 할당하거나 새로운 String instance를 생성하여 비어있는 문자열을 만들 수 있다.
var emptyString = ""               // empty string literal
var anotherEmptyString = String()  // initializer syntax
// these two strings are both empty, and are equivalent to each other
  • String 값이 비어있는지 Boolean 값으로 확인하려면 isEmpty 프로퍼티를 사용하면 된다.
if emptyString.isEmpty {
    print("Nothing to see here")
}
// Prints "Nothing to see here"

String Mutability

  • String을 변수로 선언하면 수정(modified, mutated)할 수 있지만 상수로 선언하면 수정할 수 없다.
var variableString = "Horse"
variableString += " and carriage"
// variableString is now "Horse and carriage"

let constantString = "Highlander"
constantString += " and another Highlander"
// this reports a compile-time error - a constant string cannot be modified
Note
이러한 접근 방식은 Objective-C와 Cocoa에서의 string mutation과 다릅니다. Objective-C와 Cocoa에서는 string이 수정될 수 있는지를 지칭하기 위해 두개의 클래스(NSString, NSMutableString)에서 선택해야합니다.

Strings Are Value Types

  • Swift의 String은 value type이다.
  • 함수나 메서드에 String 값이 넘어오거나 어느 상수나 변수에 String 값을 할당할 때 해당 값이 복사되어 사용된다.
  • 즉, 기존 String과 동일한 값을 갖는 새로운 복사본이 생긴 것이다.
  • 자세한 내용은 Structures and Enumeration Are Value Types 를 확인한다.
  • Swift에서 기본적으로 복사하기 때문에 출처와 관계없이 정확한 String 값을 가질 수 있다.
  • 즉 사용자 자신이 수정하기 전까지는 내용물이 수정되지 않는다.
  • Swift 컴파일러는 문자열 사용을 최적화해서 실제로는 꼭 필요한 경우에만 복사된다.
  • 따라서 string이 값 타입이지만 좋은 성능을 낼 수 있다.

Working with Characters

  •  for-in loop을 사용하여 반목문을 돌려서 String의 각 Character에 접근할 수 있다.
for character in "Dog!🐶" {
    print(character)
}
// D
// o
// g
// !
// 🐶
  • Character 한 문자만 표현하기 위해 다음과 같이 선언해줄 수 있다.
let exclamationMark: Character = "!"
  • Character 배열을 String 생성자의 인자로 사용하여 String 값을 만들 수 있다.
let catCharacters: [Character] = ["C", "A", "T", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
// Prints "Cat!🐱"

Concatenating Strings and Characters

  • String 값은 + 연산자를 활용하여 서로 결합된 새로운 String 값을 생성할 수 있다.
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
// welcome now equals "hello there"
  • 덧셈 할당 연산자 += 을 사용하여 기존의 String 값에 어느 String값을 추가할 수 있다.
var instruction = "look over"
instruction += string2
// instruction now equals "look over there"
  • append 메서드를 사용하여 String 값에 Charactert 값을 추가할 수 있다.
let exclamationMark: Character = "!"
welcome.append(exclamationMark)
// welcome now equals "hello there!"
Note
Character type의 변수에는 String 혹은 Character 값을 추가(append)할 수 없습니다. Character 값은 반드시 오직 하나의 character 만 포함해야하기 때문입니다.

 

  • multiline string literal을 사용하면 제일 마지막 줄을 제외한 나머지에 linebreak이 적용된다.
let badStart = """
one
two
"""
let end = """
three
"""
print(badStart + end)
// Prints two lines:
// one
// twothree

let goodStart = """
one
two

"""
print(goodStart + end)
// Prints three lines:
// one
// two
// three
  • 여러 줄의 String을 사용할 때, 마지막 줄을 공백으로 두어야 새로운 문자나 String을 추가할 때 linebreak이 적용된다.

String Interpolation

  • 기존의 String literal에 상수, 변수, literal, 연산식을 포함시켜서 새로운 String을 생성시켜주는 방법이다.
  • String literal에 삽입할 값을 \() 로 감싸는 방법으로 String Interpolation을 사용할 수 있다.
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"
  • 위 코드에서 보이는 것처럼 \(multiplier)을 사용해서 String literal에 multiplier의 실제 값이 삽입되었다.
  • 이어서 보이는 \(Double(multiplier) * 2.5)에서도 실제 계산된 결과 값이 삽입되었다.
  • String Interpolation에서도 # 을 사용하여 실제로 문자열 보간 효과가 적용되는 것을 막을 수 있다.
print(#"Write an interpolated string in Swift using \(multiplier)."#)
// Prints "Write an interpolated string in Swift using \(multiplier)."

print(#"6 times 7 is \#(6 * 7)."#)
// Prints "6 times 7 is 42."

Unicode

  • Unicode는 서로 다른 writing system에서 텍스트를 인코딩, 표현 및 처리를 위해 사용되는 국제 표준이다.
  • 대다수 언어의 문자는 표준화된 형식으로 표현할 수 있으며 외부 소스나 텍스트 파일, 웹 페이지에서도 문자를 읽고 쓸 수 있다.
  • Swift의 String과 Character type 또한 완벽하게 Unicode와 호환된다.

 

Unicode Scalar Values

  • Swift의 native String type은 Unicode scalar 값으로 구성된다.
  • Unicode scalar value는 어느 문자나 수정자에 대한 고유(unique) 21-bit 숫자이다.
  • U+0061은 영어 소문자 A ("a"). U+1F425는 정면을 보이는 병아리 ("🐥")

 

Extended Grapheme Clusters

  • Swift의 모든 Character type은 하나의 확장된 grapheme 클러스터를 나타낸다.
  • 확장된 Grapheme Cluster는 한개 이상의 Unicode Scalar 시퀀스로 사람이 읽을 수 있는 문자를 생성한다.
  • 예를 들어 문자 é 는 하나의 Unicode scalar é (U+00E9)으로 표현될 수 있다.
  • 하지만 문자 é 를 (LATIN SMALL LETTER E, or U+0065), COMBINING ACUTE ACCENT (U + 0301) 로도 표현할 수 있다.
  • 액센트 모양의 scalar는 Unicode-aware 텍스트 렌더링 시스템이 적용되어 e를é로 바꿔준다.
let eAcute: Character = "\u{E9}"                  // é
let combinedEAcute: Character = "\u{65}\u{301}"   // e followed by  ́
// eAcute is é, combinedEAcute is é
  • Extended grapheme clusters 는 많은 복잡한 script 문자들을 하나의 Character 값으로 표현할 수 있는 유연한 방법이다.
  • 예를 들어 한글은 자음과 모음이 이미 합쳐진 형태 혹은 분리된 형태로 표현될 수 있다.
  • 두 표현 모두 Swift에서는 하나의 Character 값을 나타난다.
let precomposed: Character = "\u(D55C)"                 // 한
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}"  // ㅎ, ㅏ, ㄴ
// precomposed is 한, decomposed is 한
  • Extended grapheme clusters는 어느 scalar를 원형 모양 안에 넣어서 Character 값을 만들 수 있다.
let enclosedEAcute: Character = "\i{E9}\u{20DD}"
// enclosedEAcute is Circle(é)
  • Unicode scalar은 국가 Symbole을 의미하는 Character 결합을 통해 국기를 생성할 수 있다.
let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
// regionalIndicatorForUS is 🇺🇸

Counting Characters

  • String의 Character 값의 개수를 얻기 위해서 String의 count 프로퍼티를 사용할 수 있다.
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
print("unusualMenagerie has \(unusualMenagerie) characters")
// Prints "unusualMenagerie has 40 characters"
  • Extended grapheme cluster에서 두개 이상의 scalar로 이루어진 Character는 String의 문자 수에 영향을 주지 않는다.
var word = "cafe"
print("the number of characters in \(word) is \(word.count)")
// Prints "the number of characters in cafe is 4"

word += "\u{301}"    // COMBINING ACUTE ACCENT, U+0301

print("the number of characters in \(word) is \(word.count)")
// Prints "the number of characters in café is 4"
Note
Extended grapheme clusters는 여러개의 Unicode scalar 값으로 구성될 수 있습니다. 즉, 다른 문자 혹은 같은 문자의 다른 표현에서는 서로 다른 메모리 공간을 사용할 수 있다는 의미입니다. Swift의 String 표현에서의 Character는 각각 동일한 메모리양을 사용하지 않습니다. 결과적으로 string에서 문자의 갯수를 count하기 위해서 string을 순회하면서 세어야 합니다. 긴 String에 대해서도 count 작업을 할 때 string 전체를 순회한다는 점을 알고있어야 합니다.

count 프로퍼티가 반환하는 문자의 개수와 NSString의 length 프로퍼티가 반환하는 문자의 수와 다를 수 있습니다. NSString은 UTF-16 표현에서 16비트 코드 단위로 문자의 개수를 세기 때문입니다.

Accessing and Modifying a String

  • String의 메서드, 프로퍼티 혹은 subscript 문법을 사용하여 해당 String에 접근하거나 수정할 수 있습니다.

 

String Indices

  • 각 String 값은 index type과 연관(associated)되어 있다.
  • String.Index는 string의 각 Character의 위치에 상응(corresponds)한다.
  • 위에서 언급했드시 각 문자마다 서로 다른 메모리 양을 갖고 있을 수 있기 때문에 String 문자열은 정수값 Index를 가질 수 없다.
  • startIndex 프로퍼티는 String의 첫번째 문자의 위치에 접근하기위해 사용할 수 있다.
  • endIndex 프로퍼티는 String의 마지막 문자 (다음)을 가리키고 있기 때문에 subscript로 접근할 때 유효한 위치가 아니다.
  • 만약 String이 비어있다면 startIndex와 endIndex는 동일하다.
  • String의 index(before:), index(after:)를 사용해서 주어진 인덱스의 이전 값 혹은 이후값에 접근할 수 있다.
  • index(_:offset:) 메서드를 통해 주어진 인덱스로부터 멀리 떨어진 index에 접근할 수 있다.
let greeting = "Guten Tag!"
greeting[greeting.startIndex]
// G
greeting[greeting.index(before: greeting.endIndex)]
// !
greeting[greeting.index(after: greeting.startIndex)]
// u
let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index]
// a
  • indices 프로퍼티를 사용하여 String의 모든 인덱스에 접근할 수 있다.
for index in greeting.indices {
    print("\(greeting[index]) ", terminator: "")
}
// Prints "G u t e n  T a g ! "
Note
Collection 프로토콜을 만족시키는 어떠한 type라면 startIndex, endIndex 프로퍼티와 index(before:), index(after:) 그리고 index(_:offsetBy:) 메서드를 사용할 수 있습니다. 현재는 String Type에서의 예시를 보여주지만 Array, Dictionary, Set과 같은 Collection 타입에서도 사용할 수 있습니다.

 

Inserting and Removing

  • String의 특정 인덱스하나의 문자삽입하려면 insert(_:at:) 메서드를 사용해야한다.
  • String의 특정 인덱스다른 String삽입하려면 insert(contentsOf:at:) 메서드를 사용해야한다.
var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
// welcome now equals "hello!"

welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there!"
  • String의 특정 위치한 문자를 제거(remove)하기 위해서 remove(at:) 메서드를 사용할 수 있다.
  • String의 특정 범위부분 문자열(substring)을 제거하기 위해서 removeSubrange(_:) 메서드를 사용한다.
welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there"

let range = welcome.index(welcome.endIndex, offset: -6)..<welcome.endIndex
welcome.removeSubrange(range)
// welcome now equals "hello"
Note
insert(_:at:), insert(contentsOf:at:), remove(at:), removeSubrange(_:) 메서드는 RangeReplaceableCollection 프로토콜을 만족하는 type에서 사용할 수 있습니다. String을 포함하여 Array, Dictionary, Set과 같은 Collection type에서도 사용할 수 있습니다.

Substrings

  • String에서 prefix(_:)와 같은 메서드로 substring을 갖고 오면 결과는 Substring의 인스턴스가 된다.
  • Substring은 String과 대부분 동일한 메서드를 갖고 있기 때문에 String과 같은 방식으로 사용할 수 있다.
  • Substring은 String에 대해 짧은시간 동안 작업해야할 때 사용한다.
  • Substring의 결과물을 좀 더 오랜시간 동안 사용하려면 String으로 만들어줘야 한다.
let greeting = "Hello, world!"
let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
let beginning = greeting[..<index]
// beginning is "Hello"

// Convert the result to a String for long-term storage.
let newString = String(beginning)
  • String과 마찬가지로 Substring도 Character들을 저장할 메모리 공간을 사용한다.
  • String과 Substring의 차이점은 성능 최적화 측면에서 원본 String 혹은 다른 Substring을 저장하는 메모리의 부분을 재사용한다.
  • String에서도 두 String의 값이 동일하면 비슷한 최적화 기능을 사용한다.
  • 성능 최적화가 수행되고 있기 때문에 String이나 Substring을 수정하는 동안 복사하는 비용을 생각할 필요가 없다.
  • Substring은 원본 String을 재사용하기 때문에 substring을 사용하는 동안에는 기존의 String을 메모리에 보관해야한다.
  • 따라서 오랜 시간 동안 활용하기에 좋은 선택은 아니다.

Note
String과 Substring이 StringProtocol 프로토콜을 만족시키기 때문에 StringProtocol의 string-manipulation 함수를 사용하는데 편리합니다. 이와 같은 함수들은 String과 Substring 값에서 호출할 수 있습니다.

Comparing Strings

  • Swift는 텍스트 값을 비교하기 위해 세가지 방법을 제공한다.
  • string and character equality, prefix equality, suffix equality.

 

String and Character Equality

  • string and character equality는 동일함 == 연산자와 동일하지안음 != 연산자로 확인할 수 있다.
let quotation = "We're a lot alike, you and I."
let sameQuotation = "We're a lot alike, you and I."
if quotation == sameQuotation {
    print("These two strings are considered equal")
}
// Prints "These two strings are considered equal"
  • Extended grapheme clusters가 동일한 경우 두 문자열 혹은 두 문자는 동일하게 취급된다.
// "Voulez-vous un café?" using LATIN SMALL LETTER E WITH ACUTE
let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"

// "Voulez-vous un café?" using LATIN SMALL LETTER E and COMBINING ACUTE ACCENT
let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"

if eAcuteQuestion == combinedEAcuteQuestion {
    print("These two strings are considered equal")
}
// Prints "These two strings are considered equal"
  • 영어에서의 라틴 대문자 A는 러시아어 대문자 A는 동일하게 보이지만 서로 다른 문자이다.
let latinCapitalLetterA: Character = "\u{41}"

let cyrillicCapitalLetterA: Character = "\u{0410}"

if latineCapitalLetterA != cyrillicCapitalLetterA {
    print("These two characters aren't equivalent.")
}
// Prints "These two characters aren't equivalent."
Note
Swift에서 String과 character은 locale-sensitive 하지 않습니다.

 

Prefix and Suffix Equality

  • 문자열에서 특정 접두사(prefix), 접미사(suffix)가 있는지 확인하려면 hasPrefix(_:), hasSuffix(_:) 메서드를 사용하면 된다.
  • Shakespears의 로미오와 줄리엣에서 첫 두가지 막에 대한 장면의 위치를 나타내는 String 배열이다.
let romeoAndJuliet = [
    "Act 1 Scene 1: Verona, A public place",
    "Act 1 Scene 2: Capulet's mansion",
    "Act 1 Scene 3: A room in Capulet's mansion",
    "Act 1 Scene 4: A street outside Capulet's mansion",
    "Act 1 Scene 5: The Great Hall in Capulet's mansion",
    "Act 2 Scene 1: Outside Capulet's mansion",
    "Act 2 Scene 2: Capulet's orchard",
    "Act 2 Scene 3: Outside Friar Lawrence's cell",
    "Act 2 Scene 4: A street in Verona",
    "Act 2 Scene 5: Capulet's mansion",
    "Act 2 Scene 6: Friar Lawrence's cell"
]
  • hasPrefix(_:) 메서드를 사용하여 Act 1이 담당해야하는 장면의 갯수를 셀 수 있다.
var act1SceneCount = 0
for scene in romeoAndJuliet {
    if scene.hasPrefix("Act 1 ") {
        act1SceneCount += 1
    }
}
print("There are \(act1SceneCount) scenes in Act 1")
// Prints "There are 5 scenes in Act 1"
  • hasSuffix(_:) 메서드도 유사한 방식으로 사용할 수 있다.
var mansionCount = 0
var cellCount = 0
for scene in romeoAndJuliet {
    if scene.hasSuffix("Capulet's mansion") {
        mansionCount += 1
    } else if scene.hasSuffix("Friar Lawrence's cell") {
        cellCount += 1
    }
}
print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
// Prints "6 mansion scenes; 2 cell scenes"
Note
hasPrefix(_:) 및 hasSuffix(_:) 메서드는 문자열 및 문자 동등성에 설명된 대로 각 문자열의 확장 그래핀 클러스터 간에 문자별 표준 동등성을 비교합니다.

Unicode Representations of Strings

  • Unicode 문자열을 텍스트 파일이나 다른 Storage에 쓸 경우 해당 문자열의 유니코드 스칼라는 유니코드 정의 인코딩 양식 중 하나로 인코딩 된다.
  • 각 폼은 코드 단위라고 하는 작은 조각(chunk)로 문자열을 인코딩 한다.
  • UTF-8 인코딩 양식(8비트 코드 단위로 인코딩), UTF-16 인코딩 양식(16비트 코드 단위로 인코딩) 및 UTF-32 인코딩 양식(32비트 코드 단위로 인코딩)이 포함된다.
  • Swift는 Unicode 표현으로 이루어진 String 값에 접근하기 위한 여러가지 방법을 제공한다.
  • String을 for-in 반복문을 사용하여 Unicode extended grapheme clusters로 이루어진 각 Character 값에 접근할 수 있다.
  • 대안으로 UTF-8, UTF-16, 21-bit Unicode scalar 값의 모음 형태로 String 값에 접근할 수 있다.
let dogString = "Dog!!🐶"
  • 위 코드의 세가지 Unicode 표현 방법을 살펴보자!

 

UTF-8 Representation

  • utf8 프로퍼티로 반복함으로써 String의 UTF-8 표현에 접근할 수 있다.
  • utf8 프로퍼티는 String.UTF8View type을 갖고 있으며 unsigned 8-bit (uInt8) 값의 컬렉션이다.
  • 실제 표현은 다음과 같다.

for codeUnit in dogString.utf8 {
    print("\(codeUnit) ", terminator: "")
}
print("")
// Prints "68 111 103 226 128 188 240 159 144 182 "
  • 위의 예시에서 처럼 3개의 10진수 code unit 값인 (68, 111, 103)은 문자 D, o, g를 나타내며 UTF-8 표현은 ASCII 표현과 동일하다.
  • (226, 128, 188)은 DOUBLE EXCLAMATION MARK 문자의 3바이트 UTF-8 표현법이다.
  • (240, 159, 144, 182)은 DOG FACE의 4바이트 UTF-8 표현법이다.

 

UTF-16 Representation

  • utf16 프로퍼티를 반복함으로써 String의 UTF-16 표현에 접근할 수 있다.
  • utf16 프로퍼티는 String.UTF16View type을 갖으며 unsigned 16-bit (UInt16) 값의 컬렉션이다.

for codeUnit in dogString.utf16 {
    print("\(codeUnit) ", terminator: "")
}
print("")
// Prints "68 111 103 8252 55357 56374 "
  • 다시 반복해서 (68, 111, 103)은 String의 UTF-8 표현과 UTF-16 표현이 동일하게 D, o, g로 나타난다.
  • 두개의 느낌표 !! 는 8252로 표현되는데 16진수값 Unicode Scalar U+203C를 10진법으로 변환한 것이다.
  • DOG FACE 문자는 UTF-16 대리(surrogate) 쌍 표현으로 U+D83D(10진수 값 55357)의 고대칭 값과 U+DC36(10진수 값 56374)의 저대칭 값을 나타낸다.

 

Unicode Scalar Representation

  • unicodeScalars 프로퍼티를 반복함으로써 String의 Unicode Scalar 표현에 접근할 수 있다.
  • unicodeScalars 프로퍼티는 UnicodeScalarView type을 갖으며 UnicodeScalar 값의 컬렉션이다.
  • 각 UnicodeScalar 값은 scalar의 21-비트 value 값을 반환하는 프로퍼티를 갖고 있으며 UInt32 값 범위를 표현한다.

for scalar in dogString.unicodeScalars {
    print("\(scalar.value) ", terminator: "")
}
print("")
// Prints "68 111 103 8252 128054
  • 위 코드에서는 value 프로퍼티를 통해 값을 조회했지만 String Interpolation을 사용하여 String 값을 갖도록 할 수 있다.
for scalar in dogString.unicodeScalars {
    print("\(scalar) ")
}
// D
// o
// g
// !!
// 🐶
반응형