
이 글은 https://bbiguduk.gitbook.io/swift 에 나오는 스위프트 문법을 공부하면서 새롭게 알게 된 지식들을 정리한 포스팅입니다.
String 타입은 Foundation의 NSString 클래스와 연결되어 있다.Foundation을 import 하면 캐스팅 없이 String 타입으로 NSString 메서드 사용 가능하다.“””을 사용한다. (다음 줄부터 입력 시작)“”” 안에서 줄바꿈을 하되 적용하지 않을 때는 \를 사용한다.“ 사용이 가능하다.\0 (null 문자), \\ (역슬래시), \" (쌍따옴표) 와 \' (홑따옴표) 등\\u{n} 로 쓰여진 임의의 유니코드 스칼라 값. 여기서 n 은 1-8 자리의 16진수String 값을 만들 때는 빈 문자열 리터럴을 할당하거나 String() 초기화 함수를 사용한다.String 값은 Bool 타입 프로퍼티인 isEmpty로 비어있는지 확인할 수 있다.String 타입은 값 타입(value type)이다.Character 타입의 상수 변수로 할당될 수 있다.String 초기화 함수로 Character 타입의 배열을 String 타입의 값으로 바꿀 수 있다.let animals: [Character] = ["🐶", "🐱", "🐭", "🐠", "🐦"]
let animalString = String(animals) // 🐶🐱🐭🐠🐦
String의 append() 메서드를 사용하여 String이나 Character 값을 추가할 수도 있다.Character 타입은 하나의 문자만 가능하기 때문에 추가 불가능하다.let dragon: Character = "🐲" // String 타입도 가능하다
animalString.append(dragon) // 🐶🐱🐭🐠🐦🐲
String 타입은 21-bit 유니코드 스칼라 값(ex: U+0061 == “a”)으로부터 생성된다.let eAcute: Character = "\u{E9}" // é
let combinedEAcute: Character = "\u{65}\u{301}" // e + ́
print(eAcute, combinedEAcute) // é é
let precomposed: Character = "\u{D55C}" // 한
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ㅎ + ㅏ + ㄴ
print(precomposed, decomposed) // 한 한
String의 count 프로퍼티에 영향을 주지 않는다. (ex: 한글)Character는 String 안에서 동일한 양의 메모리를 차지하지 않는다.String의 count 프로퍼티는 전체 유니코드 스칼라 값을 순회하며 EGC를 계산하여 결정된다.UTF-16)으로 인코딩하는 NSString의 length 프로퍼티와 값이 다를 수 있다.var word = "cafe"
print(word, word.count) // cafe 4
word += "\u{301}"
print(word, word.count) // café 4
String은 각 Character의 위치에 해당하는 index type의 String.Index 프로퍼티를 가진다.Character가 EGC이기 때문에 저장할 메모리의 양이 다르므로, 특정 위치의 문자의 인덱스를 확인하려면 앞에 위치한 문자들의 유니코드 스칼라 값을 순차적으로 계산해야 한다. → 정수 인덱스 불가.startIndex: String의 첫번째 문자 위치 / endIndex: String의 마지막 문자 다음 위치.startIndex와 endIndex가 같다. (nil 없음)String의 index(_:offsetBy:) 메서드로 특정 위치의 인덱스에 접근할 수 있다. (-도 가능)String의 indices 프로퍼티를 사용하여 각 문자의 인덱스가 담긴 배열에 접근할 수 있다.Collection 타입들(Array, Dictionary, Set)에서도 동일하게 사용 가능하다.let greeting = "안녕하세요!"
greeting[greeting.startIndex] // 안
// greeting[greeting.endIndex]
// 마지막 문자 다음 위치여서 에러
greeting[greeting.index(after: greeting.startIndex)] // 녕
// greeting[greeting.index(before: greeting.startIndex)]
// 첫 문자 전 위치여서 에러
greeting[greeting.index(before: greeting.endIndex)] // !
// greeting[greeting.index(after: greeting.endIndex)]
// 마지막 문자 다음 다음 위치여서 에러
greeting[greeting.index(greeting.startIndex, offsetBy: 5)] // !
// greeting[greeting.index(greeting.startIndex, offsetBy: 6)]
// 마지막 문자 다음 위치여서 에러
for index in greeting.indices {
print("\(greeting[index]) ", terminator: "") // 안 녕 하 세 요 !
}
insert(_:at:) / remove(at:) : 문자 하나를 삽입/삭제한다.insert(contentsOf:at:) / removeSubrange(_:) : 문자열/특정 범위 부분을 삽입/삭제한다.Collection 타입들도 사용가능한 메서드들이다.greeting.insert("?", at: greeting.endIndex) // 안녕하세요!?
greeting.insert(contentsOf: " 주인님!", at: greeting.endIndex) // 안녕하세요!? 주인님!
greeting.remove(at: greeting.index(greeting.startIndex, offsetBy: 6))
// 안녕하세요! 주인님!
greeting.removeSubrange(greeting.index(greeting.endIndex, offsetBy: -5)..<greeting.endIndex)
// 안녕하세요!
prefix(_:)와 같은 메서드로 추출한 부분 문자열은 Substring 타입 인스턴스가 된다.str[str.startIndex] 등의 대괄호([])를 써서 인덱스에 접근하는 방식을 말함)SubSting도 StringProtocol을 준수하기 때문에 String의 거의 모든 메서드를 사용할 수 있다.SubString은 원래 문자열을 저장하는데 사용된 메모리의 일부를 재사용한다.```swift
let greeting = "Hello, World!"
let beginning = greeting[..<(greeting.firstIndex(of: ",") ?? greeting.endIndex)]
let newString = String(beginning)
beginning[...beginning.index(after: beginning.startIndex)] // He
// SubString에서도 SubString을 추출해 낼 수 있다.
```
String 혹은 Character 값의 확장된 문자소 클러스터가 동일할 경우 값이 같다고 한다.let han = "\u{D55C}" // 한
let hanCombined = "\u{1112}\u{1161}\u{11AB}" // ㅎ + ㅏ + ㄴ
print(han == hanCombined) // true
hasPrefix(_:) / hasSuffix(_:) : 특정 접두사/접미사를 가지고 있는지 확인한다.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",
//...
]
var cnt = 0
for scene in romeoAndJuliet {
if scene.hasPrefix("Act 1") {
// if scene.hasSuffix("Capulet's mansion") {
cnt += 1
}
}
print(cnt)
String의 프로퍼티로 세 가지 인코딩 형식 중 각각의 코드 유닛에 접근할 수 있다.utf8(UTF-8), utf16(UTF-16), unicodeScalars(UTF-32: 21-bit 유니코드 스칼라 값)utf8 : 이 프로퍼티를 통해 String의 UTF-8 표현에 접근할 수 있다.String.UTF8View 타입으로, 각 문자 바이트(8bit-코드유닛)에 대응하는 UInt8 값의 배열이다.‼의 3바이트 UTF-8표현이고, 다음 4개 코드유닛은 🐶의 4바이트 UTF-8표현이다.let dogString = "Dog‼🐶"
for codeUnit in dogString.utf8 {
print("\(codeUnit) ", terminator: "")
}
// 68 111 103 226 128 188 240 159 144 182

utf16 : 이 프로퍼티를 통해 String의 UTF-16 표현에 접근할 수 있다.String.UTF16View 타입으로, 각 문자의 16bit-코드유닛에 대응하는 UInt16 값의 배열이다.‼의 유니코드 스칼라 값(U+203C)의 16진수 203C에 해당하는 값을 가지며 UTF-16에서 하나의 코드유닛으로 표현되고, 다음 2개의 코드유닛은 🐶의 UTF-16 대리 쌍 표현이다.for codeUnit in dogString.utf16 {
print("\(codeUnit) ", terminator: "")
}
// 68 111 103 8252 55357 56374

unicodScalars : 이 프로퍼티를 통해 String의 유니코드 스칼라 표현에 접근할 수 있다.
UnicodeScalar타입의 모음인 UnicodeScalarView 타입으로, UnicodeScalar은 각 문자에 대응하는 스칼라의 21-bit 값인 UInt32 값을 반환하는 value 프로퍼티를 가지고 있다.
UnicodeScalar는 Unicode.Scalar의 typealias다.
아래에서 첫 3개 UnicodeScalar 값은 D, o, g를 나타내며, 다음 코드유닛은 ‼의 유니코드 스칼라 값(U+203C)에 해당하는 십진수 값이며, 다음 UnicodeScalar의 value는 🐶의 유니코드 스칼라 값(U+1F436)에 해당하는 십진수 값이다.
value 프로퍼티를 사용하지 않으면 각 UnicodeScalar 에 해당하는 문자를 확인할 수 있다.
for scalar in dogString.unicodeScalars {
print("\(scalar.value) ", terminator: "")
}
// 68 111 103 8252 128054
// scalar만 프린트하면: D o g ‼ 🐶
