공식문서로 Swift 공부하기 -Strings and Characters

Strings and Characters

String은 "hello, world" 또는 "albatross" 같이 문자의 연속이다. String의 내용은 Character값의 배열을 포함하여 다양한 방법으로 엑세스할 수 있다.

Swift에서 String과 Character타입은 빠른 속도를 제공하고 Unicode-compliant (유니코드 준수) 방식으로 동작한다.
문자열 작성 및 조작 구문은 가볍고 가독성이 좋다.
String literal 구문은 C언어와 유사하다.
문자열 연결은 + 연산자로 두개의 문자열을 연결 하는것으로 쉽고 문자열의 변경 가능성은 다른 값과 마찬가지로 상수 변수를 선택하여 관리한다.
String interpolation을 이용하여 상수, 변수, 리터럴 및 식이 긴 문자열을 삽입할 수 있다. 이를 통해 custom string 값을 쉽게 만들 수 있다.
Swift의 String은 인코딩에 의존하지 않는 Unicode문자로 구성되어 있다.

NOTE
Swift의 String타입은 Foundation에 NSString class와 브릿지 되어 있고 Foundation은 String을 확장하여 NSString에 의해 정의된 메소드를 표시한다. 만약 Foundation을 import한다면 String에서 캐스팅없이 NSString 메소드에 접근할 수 있음을 의미한다.
https://developer.apple.com/documentation/swift/string#2919514

String Literals

String Literals는 큰따옴표("")로 둘러싸인 문자들의 연속이다.
상수나 변수의 초기값으로 string literal을 사용한다.

let someString = "Some string literal value"
print(someString)

Swift는 someString 상수가 string literal 값으로 초기화 되었기 때문에 String타입으로 추론한다.

Multiline String Literals

여러 줄의 문자열이 필요하면 문자들을 3개의 큰따옴표(""")로 둘러싸서 사용한다.

let quotation = """
Hello, World Hello, World Hello, World Hello, World Hello, World
Hello, World Hello, World Hello, World Hello, World Hello, World
Hello, World Hello, World Hello, World Hello, World Hello, World
"""
print(quotation)

Multiline string literal안에 위 코드처럼 하면 줄바꿈이 발생하지 않는데 줄 바꿈을 사용하려면 백슬래시()를 넣어준다

let quotation = """
Hello, World Hello, World Hello, World Hello, World Hello, World \
Hello, World Hello, World Hello, World Hello, World Hello, World \
Hello, World Hello, World Hello, World Hello, World Hello, World
"""
print(quotation)

줄 바꿈으로 시작하는 Multiline string literal을 만드려면 첫 번째나 마지막 줄을 공백으로 시작해야한다.

let quotation = """

Hello, World Hello, World Hello, World Hello, World Hello, World
Hello, World Hello, World Hello, World Hello, World Hello, World
Hello, World Hello, World Hello, World Hello, World Hello, World

"""
print(quotation)

주변 코드와 일치시키기 위해 문자열을 들여쓰기 해서 작성할 수 있다.

let lineWithIndentation = """
    이 줄은 공백 없이 시작한다.
        이줄은 4개의 공백을 가지고 시작한다.
    이 줄은 공백 없이 시작한다.
    """
print(lineWithIndentation)

Special Characters in String Literals

String literals는 다음 특수 문자들도 포함한다.

\0 (null character)
\ (backslash)
\t (horizontal tab)
\n (line feed)
\r (carriage return)
\" (double quotation mark)
\' (single quotation mark)

유니 코드를 사용할 때는 \u{n} n에 1~8자리의 16진수를 써준다.

let dollarSign = "\u{24}" // $, unicode scalart U+0024
let blackHeart = "\u{2665}" // ♥, unicode scalart U+2665
let sparklingHeart = "\u{1F496}" // 💖, unicode scalart U+1F496
print(dollarSign)
print(blackHeart)
print(sparklingHeart)

Multiline string literals에서는 (""")를 사용하기 때문에 큰 따옴표(")를 사용할 수 있다 (""")를 사용하려면 아래와 같이 사용하면 된다.

let threeDoubleQuotationMarks = """
Escaping all three quotation marks \"\"\"
"""
print(threeDoubleQuotationMarks)

Extended String Delimiters

##사이에 문자열을 넣으면 특수문자들을 문자열으로 포함할 수 있다. 예를 들면 #"Line1\nLine2"#의 경우 두 줄로 출력되지 않고 \n이 문자로 출력된다.(Line1\nLine2 이 출력됨) 만약 ##사이에 문자열을 넣고 문자열에 \n 같은 기능을 사용하고 싶다면 \와 n 사이에 #을 사용한 개수를 넣어주면 사용가능하다. (예제로 이해하는게 빠름)

let ExtendedStringDelimiters = #"Line1\#nLine2"#
let ExtendedStringDelimiters2 = ##"Line1\##nLine2"##
let ExtendedStringDelimiters3 = ###"Line1\###nLine2"###

Multiline String literals에서도 사용이 가능하다.

let threeMoreDoubleQuotationMarks = #"""
Here are three more double quotes: """
"""#

Initializing an Empty String

빈 String 값을 생성 하려면 빈 String literla(" ")을 변수에 할당하거나 initializer 구문을 사용하여 String 인스턴스를 초기화 한다.

var emptyString = "" // empty string literal
var anotherEmptyString = String() // initializer syntax
// 위 두 가지가 빈 문자열을 생성하는 방법

String 값이 비어 있는지 확인 하려면 isEmpty 프로퍼티를 사용하면 된다.

if emptyString.isEmpty {
    print("Nothing to see here")
}
// "Nothing to see here"이 출력된다.

String Mutability

String을 variable또는 constant로 할당하여 수정(또는 가변)할 수 있는지 지정할 수 있다.
variable -> 수정할 수 있음
constant -> 수정할 수 없음

var variableString = "Horse"
variableString += " and carriage"
// variableString은 "Horse and carriage"이다.

let constantString = "Highlander"
constantString += " and another Highlander"
// constantString이 상수이기 때문에 수정이 불가능 하고 컴파일 에러가 난다.
NOTE
이 접근방식은 Objective-C 및 Cocoa 문자열 변환과는 다릅니다.이 방법에서는 문자열의 변환 여부를 나타내기 위해 2개의 클래스(NSString 및 NSMutableString) 중 하나를 선택합니다. 

Strings Are Value Types

Swift에서 String은 value type이라고 한다. 만약 새로운 String값을 생성하면 함수 또는 메소드에 전달 되거나 상수 또는 변수에 할당될 때 해당 String 값은 복사 된다. -> 기존 String 값의 원본 버전이 아니고 복사본이 전달 도는 할당된다.

String을 value type으로 사용할 때 뛰어난 성능을 얻을 수 있다고 한다. -> Swift의 컴파일러가 문자열 사용을 최적화 하여 절대적으로 필요한 경우에만 복사가 이루어지도록 하기 때문

Working with Characters

for문(반복문)을 이용하여 String의 개별 Character 값에 접근할 수 있다.

for character in "Dog!🐶" {
    print(character)
}
//D
//o
//g
//!
//🐶

String literal을 이용하여 Character 타입의 상수 또는 변수를 생성할 수 있다. (Character type annotation을 제공해야함)

let exclamationMark: Character = "!"

Character 타입의 배열을 initializer에 전달하여 String 값을 구성할 수 있다.

let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
// Prints "Cat!🐱"

Concatenating Strings and Characters

String value는 +연산자를 이용하여 묶을 수 있고 그 값으로 새로운 String value를 생성할 수 있다.

let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
print(welcome)
// welcome는 "hellow there"

Addition assignment operator (+=)를 이용하여 다른 String 변수에 String value를 추가할 수 있다.

var instruction = "look over"
instruction += string2
print(instruction)
// instruction은 "look over there"

Character 값을 String변수에 추가 할때는 String 타입의 메소드 append()를 사용한다.

let exclamationMark: Character = "!"
welcome.append(exclamationMark)
print(welcome)
// welcome은 "hello there!"
NOTE
Character는 하나의 문자를 가지기 때문에 값이 있는 Character 변수에는 String이나 Character을 추가할 수 없다.

만약에 multiline string literal을 사용할 경우 모든 행의 마지막은 줄 바꿈으로 끝나야 한다. (예시로 이해하기: 3줄로 출력되게 하기)

let badStart = """
one
two
"""
let end = """
three
"""
print(badStart + end)
//두 줄이 출력된다.
//one
//twothree

let goodStart = """
one
two

"""
print(goodStart + end)
//세 줄이 출력된다.
//one
//two
//three

badStart 상수의 경우 마지막 행이 줄 바꿈으로 끝나지 않았기 때문에 end 와 +연산을 했을 때 두줄이 출력되고 goodStart 의 경우 마지막 행을 줄 바꿈으로 끝냈기 때문에 원하는 결과가 출력된다.

String Interpolation

String Interpolation은 string literal안에 다른 상수, 변수, literal, 표현식을 혼합해서 새로운 String 값을 구성하는 방법이다.
백슬래쉬 + 소괄호 (())으로 사용한다.

let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
print(message)
// message는 "3 times 2.5 is 7.5"

위의 코드 처럼 string interpolation을 사용하면 string literal안에 상수, 변수, 표현식을 넣어서 String 값을 구성할 수 있다. (String이 생성될 때 string interpolation 안은 실제 값으로 대체된다.)

Extended string delimiters(#)을 사용하면 string interpolation까지 문자열로 포함시켜서 String을 만들 수 있음.

print(#"Write an interpolated string in Swift using \(multiplier)."#)
// "Write an interpolated string in Swift using \(multiplier)."이 출력된다.

Basic operator에서 배운것처럼 string interpolation의 백슬래쉬와 소괄호 사이에 사용된 Extended string delimiters(#)의 개수 만큼 넣어주면 string interpolation을 사용할 수 있음

print(#"6 times 7 is \#(6 * 7)."#)
// "6 times 7 is 42."이 출력된다.

Unicode

Unicode는 텍스트를 인코딩, 표현, 처리하기 위한 국제 표준이다.
모든 언어의 문자를 표준화된 형식으로 나타낼 수 있고 텍스트 파일이나 웹 페이지 등의 외부 소스 문자를 읽고 쓸 수 있다.
Swift의 String, Character 타입은 Unicode와 완전히 호환된다.

Unicode Scalar Values

Swift의 native String 타입은 Unicode scalar value으로 만들어져 있다.
Unicode scalar value는 고유한 21비트 숫자이다. (("a")의 경우 U+0061, ("🐥")의 경우 U+1F425)
모든 21비트 Unicode scalar value가 문자에 할당되는 것은 아니고 일부 스칼라는 향후에 할당 되거나 UTF-16 인코딩에 사용하기 위해 예약되어 있다.
문자에 할당 되어있는 scalar값은 이름이 붙어 있다. (LATIN SMALL LETTER A -> ("a"), FORNT-FACING BABY CHICK -> ("🐥"))

Extended Grapheme Cluster

Swift의 모든 문자 타입의 인스턴스는 단일 extended grapheme cluster를 나타낸다. Extended grapheme cluster는 1개 이상의 Unicode 스칼라로 이루어진 시퀀스로, 사람이 읽을 수 있는 단이 문자를 생성한다.

예를 들어 é는 단일 Unicode scalar(LATIN SMALL LETTER E WITH ACUTE, U+00E9)로 나타낼 수 있고 해당 문자를 스칼라 쌍으로도 나타낼 수 있다. (e (LATIN SMALL LETTER E) 와 그 뒤에 COMBINING ACUTE ACCENT scalar로 나타낼 수 있음, (U+0065 )+(U+0301) )
-> Unicode-aware text-rendering system에 의해 é로 렌더링 된다.

두 가지 경우 é 는 Swift의 단일 Character 값으로 나타난다. 첫 번째 경우 단일 스칼라, 두 번째 경우 스칼라쌍으로 나타난다.

let eAcute: Character = "\u{E9}" // é
let combinedEAcute: Character = "\u{65}\u{301}" // e followed '
print(eAcute)
print(combinedEAcute)
// 둘다 é를 출력한다.

Extended grapheme clusters는 복잡한 문자 script를 하나의 Character 값으로 나타내는 유연한 방법이다.

let precomposed: Character = "\u{D55C}" // 한
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ㅎ ㅏ ㄴ
print(precomposed)
print(decomposed)
// 둘다 한 이 출력된다.

Extended grapheme clusters는 enclosing marks를 다른 Unicode scalars에 enclosing marks를 둘러쌀 수 있다.

let enclosedEAcute: Character = "\u{E9}\u{20DD}"
print(enclosedEAcute)
// é⃝이 출력된다. enclosing marks로 둘러쌈

지역 구분 심볼 Unicode scalars를 결합하여 하나의 Character 값 결합할 수 있다. (REGIONAL INDICATOR SYMBOL LETTER U and REGIONAL INDICATOR SYMBOL LETTER S)

let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
print(regionalIndicatorForUS)
// 🇺🇸이 출력된다.

Counting Characters

문자열에서 Character 값의 개수를 가져오려면 string의 count 프로퍼티를 사용한다.

let unusualMenagerie = "Koala 🐨, Bee 🐝, Snake 🪱, Penguin "
print("unusualMenagerie has \(unusualMenagerie.count) characters")
// unusualMenagerie has 33 characters이 출력된다.

Swift가 Character 값에 extended grapheme cluster를 사용한다고 문자열의 연결이나 수정이 문자열의 문자 수에 영향을 미치는 것은 아니다.

예를 들어, cafe라는 문자열의 끝에 COMBINING ACUTE ACCENT(U+0301)를 추가 해도 문자 개수는 4개로 변함이 없다.(e 가 é로 바뀌지만 문자 개수는 변함 없음)

var word = "cafe"
print("the number of characters in \(word) is \(word.count)")
// 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)")
// the number of characters in café is 4 가 출력된다.

Extended grapheme cluster는 여러 Unicode 스칼라로 구성할 수 있다. 이에 따라 다른 문자(같은 문자의 다른 표현)를 저장하기 위해 각각 다른 양의 메모리가 필요하다. 이러한 이유 때문에 Swift의 문자는 문자열 내에서 각각 동일한 양의 메모리를 차지하지 않는다.

Count 프로퍼티에 의해 반환되는 문자 수가 같은 문자를 포함하는 NSString의 length 프로퍼티와 동일하지 않다. NSString의 length는 UTF-16의 16비트 코드 유닛 수를 기반으로 하기 때문이다.

Accessing and Modifying a String

메소드 그리고 프로퍼티 또는 subscript syntax를 사용하면 문자열에 접근하거나 수정할 수 있다.

String Indices

각 문자열 값은 각각의 문자의 위치에 해당하는 관련된 인덱스 타입의 String.index 를 가지고 있다.

문자마다 다른 메모리 용량을 필요로 하기 때문에 어떤 문자가 특정 위치에 있는지 판단하려면 해당 문자열의 시작 또는 끝부터 Unicode 스칼라로 반복(컴퓨터 처리 절차를)해야한다. 이러한 이유로 Swift의 문자열은 인덱스가 정수 값이 될 수 없다.

startIndex: 문자열의 첫 번째 문자열에 접근할 수 있다.

endIndex: 문자열의 마지막 문자 다음 위치이다. 따라서 endIndex 프로퍼티는 문자열의 첨자에 대한 유효한 인자가 아니다.

문자열이 비어있다면 startIndex와 endIndex는 같다.

index(before:): 지정된 인덱스 이전

index(after: ): 지정된 인덱스 이후

index(_:offsetBy:): 지정된 인덱스에서 offsetBy값 만큼 떨어진 인덱스

Subscript syntax(_[])를 이용하여 String의 인덱스에 접근할 수 있다.

let greeting = "Guten Tag!"
print(greeting[greeting.startIndex])
// G
print(greeting[greeting.index(before: greeting.endIndex)])
// !
print(greeting[greeting.index(after: greeting.startIndex)])
// u
print(greeting[greeting.index(greeting.startIndex, offsetBy: 7)])
// a

문자열 범위 밖의 인덱스 또는 문자열 범위 밖의 인덱스에 있는 문자에 접근을 시도하면 런타임 오류가 발생한다.

print(greeting[greeting.endIndex]) // error
print(greeting[greeting.index(after: greeting.endIndex)]) // error

indices 프로퍼티를 이용하면 문자열의 모든 각각의 문자에 접근할 수 있다.

NOTE

startIndex, endIndex, index(before:), index(after:), index(_:offsetBy:) 4가지 메소드를 Collection 프로토콜을 준수하는 어떤 타입이든 사용가능하다. (String, 컬렉션 타입: Array, Dictionary, Set)

Inserting and Removing

문자열의 특정한 인덱스에 하나의 문자를 넣으려면 insert(_:at:)메소드를 사용하고 다른 문자열을 넣으려면 insert(contentsOf:at:)메소드를 사용한다.

var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
print(welcome)
// welcome은 hello! 이다.

welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
print(welcome)
// welcome은 hello there! 이다.

문자열의 특정한 인덱스에 하나의 문자를 제거하려면 remove(at:) 메소드를 사용하고 특정한 범위의 문자열을 제거하려면 removeSubrange(_:) 메소드를 사용한다.

welcome.remove(at: welcome.index(before: welcome.endIndex))
print(welcome)
// welcome은 hello there이다.

let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
print(welcome)
// welcome은 hello 이다.
NOTE
insert(_:at:), insert(contentsOf:at:), remove(at:), removeSubrange(_:) 4가지 메소드를 RangeReplaceableCollection 프로토콜을 준수하는 어떤 타입에서든지 사용가능하다. (String, 컬렉션 타입: Array, Dictionary, Set)

Substrings

문자열로 부터 substring(부분 문자열)을 가지고 올때 다른 String이 아닌 Sustring의 인스턴스를 결과로 가져온다. Swift에서 Substring은 String과 비슷한 메소드를 가진다. 그러나 String과 달리 Substring은 짧은 시간 동안만 사용하는 것이 좋다. 긴 시간동안 Substring을 저장해야 한다면 Substring을 String의 인스턴스로 변환해야한다.

let greeting = "Hello, world!"
let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
let beginning = greeting[..<index]
print(beginning)
// beginning은 "Hello"이다.
let nowString = String(beginning)
// 긴 기간동안 저장하려면 결과를 String으로 변환해준다.

Substring(부분 문자열)도 String(문자열)처럼 메모리 공간을 차지하는데 이 둘의 차이점은 성능 최적화로 substring은 원본 문자열 또는 다른 substring의 메모리의 일부를 재사용 한다. 따라서 Substring을 사용하는 한 원본 String이 메모리에 계속 남겨져 있다. 그렇기 때문에 SubString을 오래 사용하는 것은 좋지않다.

위의 코드에서 greeting은 String이다. beginning은 greeting의 Substring이기 때문에 beginning은 greeting이 사용하는 메모리를 재사용한다. NewString은 String이고 자체 스토리지가 있다. 아래 그림으로 이 관계를 나타내었다.

NOTE
String 과 Substring은 모두 StringPorotocol 프로토콜을 준수한다. 따라서 문자열을 조작하는데 편리한 함수를 두 경우에서 사용할 수 있다.

Comparing Strings

Swift는 텍스트 값을 비교하는 3가지 방법을 제공한다.

  • String and Character Equality (문자열 그리고 문자의 동등_
  • Prefix Equality (접두사의 동등)
  • Suffix Equality (접미사의 동등)

String and Character Equality

"equal to" 연산자 (==), "not equal to" 연산자 (!=)를 이용하여 문자열과 문자가 같은지 확인한다.

두 문자열 값(또는 두 개의 문자 값)의 extended grapheme clusters 가 동일한 경우 두 값이 동일한 것으로 간주된다.(extended grapheme clusters가 백그라운드에서 다른 Unicode 스칼라로 구성 되더라도 언어적인 의미와 외관이 동일한 경우 동일한 값으로 간주한다. )

let eAcuteQuestion = "Voulez-vous un caf\u{E9}"
let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}"
// 두 상수의 Unicode 스칼라 값이 다르다.
if eAcuteQuestion == combinedEAcuteQuestion {
    print("These two strings are considered equal")
}
// These two strings are considered equal이 출력된다.

위와 반대로 영어에서 사용되는 라틴 대문자 A(U+0041, "A") 와 러시아에서 사용되는 키릴 대문자 A(U+0410, "A")는 생김새는 같지만 언어적 의미는 다르기 때문에 같지 않다.

let latinCapitalLetterA: Character = "\u{41}"

let cyrillicCapitalLetterA: Character = "\u{0410}"
// 두 문자의 생김새는 같지만 언어적 의미는 다름
if latinCapitalLetterA != cyrillicCapitalLetterA {
    print("These two characters aren't equivalent.")
}
// These two characters aren't equivalent. 이 출력된다.
NOTE
Swift의 문자열과 문자의 비교는 locale-senstive하지 않다.(locale-senstive: 어떤 기능을 수행하기 위해 로케일 객체를 요구하는 동작)

개념적으로 로케일은, 컴퓨터와 사람의 상호관계나 처리하는 데이터의 종류들에 대한 문제에서, 유사한 문화적 언어적 배경을 갖는 사람들의 집합과 같은 특정 사용자 집합을 구별할 수 있게 해준다.

-> Swift에서 문자열 또는 문자 비교는 언어를 고려하지않는 다는 뜻 (언어와 상관없이 같은 문자이면 같다고 취급한다.)

Prefix and Suffix Equality

문자열의 접두사 또는 접미사의 비교를 위해 hasPrefix(:), hasSuffix(:) 메소드를 사용할 수 있다. (String 타입의 단일 인자를 사용하고 부울 값을 리턴한다.)

Unicode Representations of Strings

Unicode 문자열이 텍스트 파일 또는 기타 저장소에 기록될 때 문자열의 Unicode scalar는 Unicode 인코딩 형식 중 하나로 인코딩된다.

  • UTF-8: 문자열을 8비트 코드 단위로 인코딩
  • UTF-16: 문자열을 16비트 코드 단위로 인코딩
  • UTF-32: 문자열을 32비트 코드 단위로 인코딩

Swift는 문자열의 Unicode표현에 접근하는 몇 가지의 방식을 제공한다.
3가지 Unicode 표현 방식으로 String 값에 접근할 수 있다.

  • UTF-8 코드 유닛 집합 (문자열의 utf8 프로퍼티로 접근)
  • UTF-16 코드 유닛 집합 (문자열의 utf16 프로퍼티로 접근)
  • UTF-32 인코딩 형식과 동일한 21비트 Unicode scalar 값 집합 (문자열의 unicodeScaclars 프로퍼티로 접근)
let dogString = "Dog!!🐶"

위 문자열의 3가지 Unicode 표현방식

UTF-8 Representation

문자열의 utf8 프로퍼티를 반복하여 UTF-8 표현방식에 접근할 수 있다.
utf8 프로퍼티는 String.UTF8View 타입, 부호가 없는 8비트 값들의 집합이다.

for codeUnit in dogString.utf8 {
    print("\(codeUnit) ", terminator: "")
}
// 68 111 103 226 128 188 240 159 144 182 이 출력된다.

첫 번째 십진수 codeUnit(68, 111, 103) 3개는 문자 D, o, g를 표현하고 이는 ASCII 표현과 동일하다. 그 다음 codeUnit (226, 128, 188)3개는 3바이트 UTF-8 표현인 DOUBLE EXCLAMATION MARK 문자이다. 마지막 codeUnit 4개는 3바이트 UTF-8 표현인 DOG FACE 문자이다.

UTF-16 Representation

문자열의 utf16 프로퍼티를 반복하여 UTF-16 표현방식에 접근할 수 있다.
utf16 프로퍼티는 String.UTF16View 타입, 부호가 없는 16비트 값들의 집합이다.

for codeUnit in dogString.utf16 {
    print("\(codeUnit) ", terminator: "")
}
// 68 111 103 8252 55357 56374 이 출력된다.

첫 번째 codeUnit 3개는 UTF-8 표현방식과 같다. (그 이유는 이것들의 Unicode scalar가 ASCII character를 표현하기 때문)
네 번째 codeUnit(8285, 느낌표 두개)은 16진수 203C를 십진수로 변환한 것이다.
다섯, 여섯 번째 codeUnit(55357 and 56374)은 DOG FACE를 UTF-16쌍으로 표현한 것이다.

Unicode Scalar Representation

문자열의 unicodeScalars 프로퍼티를 반복하여 Unicode scalar 표현방식에 접근할 수 있다.
unicodeScalars 프로퍼티는 UnicodeScalarView 타입, UnicodeScalar 타입인 값들의 집합이다.

for scalar in dogString.unicodeScalars {
    print("\(scalar.value) ", terminator: "")
}
// 68 111 103 8252 128054  이 출력된다.

4 번째 codeUnit 값 까지는 UTF-16과 동일하다. 마지막 codeUnit(128054) Unicode scalar U+1F436(DOG FACE)를 표현하는 16진수 1F436의 십진수 변환이다.

각각의 UnicodeScalar value로 새로운 String 값을 구성할 수 있다.

for scalar in dogString.unicodeScalars {
    print("\(scalar)")
}
//D
//o
//g
//‼
//🐶

출처 : the swift programming language swift 5.6

좋은 웹페이지 즐겨찾기