본문 바로가기

iOS/Swift

Swift 공식 문서 3. Strings and Characters (2)

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters

 

Documentation

 

docs.swift.org

 

Swift 공식 문서 보면서 내 맘대로 정리


 

String Indices

문자열의 인덱스와 String.Index 타입

  • String에는 각 Character의 위치를 나타내는 String.Index 타입이 있다.
  • Swift 문자열은 정수 값으로 직접 인덱싱할 수 없다.
    • 문자들이 차지하는 메모리 크기가 다를 수 있기 때문에, 특정 위치의 문자를 찾기 위해서는 문자열의 시작 또는 끝에서 부터 유니코드 스칼라를 하나씩 탐색해야 한다.

 

startIndex와 endIndex

  • startIndex : 문자열의 첫 번째 문자의 위치
  • endIndex : 문자열의 마지막 문자 바로 다음 위치
    • subscript시에 valid 하지 않은 범위임에 유의
    • 빈 문자열이면 startIndex와 endIndex 같음

 

인덱스 접근 및 subscript

  • index(before:) : 주어진 인덱스의 뒤를 접근
  • index(after:) :  주어진 인덱스의 앞에 접근
  • index(_:offsetBy:) : 주어진 인덱스에서 떨어진 위치 
  • subscript : 특정 String.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

greeting[greeting.endIndex] // Error
greeting.index(after: greeting.endIndex) // Error

 

indices

  • 컬렉션에서 subscript를 사용해 접근할 수 있는 모든 유효한 인덱스들을 오름차순으로 반환
  • 이 indicies는 Collection을 채택한 타입들에서 사용할 수 있음
  • 다만 여기 Discussion을 보면 indices와 Collection이 강한 참조를 가질 수 있다고 하니, 유의하여 사용하는게 좋을 듯
for index in greeting.indices {
    print("\(greeting[index]) ", terminator: "")
}

 

Inserting and Removing

삽입

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!"

 

삭제

welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there"


let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
// welcome now equals "hello"

 

Substrings

  • String과 동일하게 StringProtocol 을 준수
    • 문자열 조작 메서드들이 StringProtocol을 받고는 한다.
  • String의 문자열 중 일부를 추출할 때 반환되는 결과는 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)

 

 

메모리

  • Substring도 String과 동일하게 Character들이 저장된 메모리 영역을 갖는다.
  • 성능 최적화를 위해 원본 String에 사용된 메모리의 일부를 재사용하거나 다른 Substring에 사용된 메모리의 일부를 재사용할 수 있다.
    • String 또는 Substring이 수정하기 전까지 메모리를 복사하는데 드는 성능 비용을 지불하지 않아도 된다.
    • 단기적인 사용 목적인 이유는 Substring이 남아있는 한 원본 String이 메모리에 남아 있어야 하기 때문이다.

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters/#String-Indices

 

 

참고 : 컴파일 시점에 그 크기를 명확히 알기 어려운 String 또는 Collection 타입들은 Value Type이지만 Heap 영역에 값을 저장할 수 있다

ㄴ 출처

Comparing Strings

String & Character Equality

  • 비교 연산자(==, !=)를 통해 비교 가능
  • Extended graphme Cluster가 동일한 언어적 의미와 외형을 갖는 경우 갖다고 판단
  • Swift에서 문자열 비교는 지역/언어 설정에 따라 달라지지 않는다.
// "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"

 

Prefix and Suffix Equality

  • hasPrefix(_:)
  • hasSuffix(_:)

 

Unicode Representations of Strings

유니코드 문자열이 텍스트 파일이나 저장소에 기록될 때, 유니코드 스칼라는 여러 유니코드 인코딩 방식 중 하나로 인코딩 된다.

let dogString = "Dog‼🐶"

print("UTF-8 Code Units:")
for codeUnit in dogString.utf8 {
    print(codeUnit, terminator: " ")
}

//68 111 103 226 128 188 240 159 144 182


print("\n\nUTF-16 Code Units:")
for codeUnit in dogString.utf16 {
    print(codeUnit, terminator: " ")
}

// 68 111 103 8252 55357 56374


print("\n\nUnicode Scalars:")
for scalar in dogString.unicodeScalars {
    print(scalar.value, terminator: " ")
}
// 68 111 103 8252 128054
  • UTF-8 : 문자열을 8 bit 코드 유닛으로 인코딩
    • 특징 
      • 가변 길이 인코딩 방식
      • 각 문자를 1바이트에서 4바이트 사이의 가변 길이로 인코딩
    • 장점
      • ASCII 문자와 호환
      • 메모리 사용 효율 높음
    • 단점
      • 복잡한 문자나 이모지 표현시 3~4 바이트를 사용하므로 처리 속도가 좀 더 느릴 수 있음
    • Swift
      • string의 utf8 프로퍼티 (String.UTF8View 타입)
      • UTF-8 표현을 나타내는 UInt8 값들의 컬렉션

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters/#UTF-8-Representation

  • UTF-16 : 문자열을 16 bit 코드 유닛으로 인코딩
    • 특징 
      • 가변 길이 인코딩 방식
      • 대부분의 문자들은 2바이트로 인코딩. 일부 복잡한 문자는 4바이트(surrogate pair)로 인코딩
    • 장점
      • 대부분의 문자들을 2바이트로 표현할 수 있어, 다양한 언어에 대한 균형 잡힌 크기와 처리 속도 제공
    • 단점
      • ASCII와 호환되지 않음
      • surrogate pair를 처리하는 추가 로직이 필요
    • Swift
      • string의 utf16 프로퍼티 (String.UTF16View 타입)
      • UTF-16 표현을 나타내는 UInt16 값 들의 컬렉션
      • DOG FACE 문자는 surrogate 페어로 표현됨
        • high-surrogate value : U+D83D > 55357
        • low-surrogate value : U+DC36 > 56374

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters/#UTF-16-Representation

  • Unicode Scalar Representation : 문자열을 21 bit 유니코드 스칼라 값으로 인코딩
    • 특징
      • 고정 길이 인코딩 방식
      • 모든 문자를 4바이트로 인코딩
    • 장점 
      • 모든 문자를 동일한 크기로 표현하므로, 인덱싱과 같은 작업에서 단순하고 빠름
    • 단점
      • 메모리 사용 비효율
    • Swift
      • string의 unicdeScalars 프로퍼티 ( UnicodeScalarView 타입)
      • UInt32 값들의 컬렉션

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters/#Unicode-Scalar-Representation

 

'iOS > Swift' 카테고리의 다른 글