IT story

Swift에서 String.Index는 어떻게 작동합니까?

hot-time 2020. 9. 8. 22:02
반응형

Swift에서 String.Index는 어떻게 작동합니까?


Swift 3로 이전 코드와 답변 중 일부를 업데이트했지만 Swift Strings and Indexing에 도달했을 때 사물을 이해하는 것이 고통 스러웠습니다.

구체적으로 다음을 시도했습니다.

let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5) // error

두 번째 줄에서 다음 오류가 발생했습니다.

'advancedBy'를 사용할 수 없음 : 인덱스를 n 단계 앞으로 진행하려면 인덱스를 생성 한 CharacterView 인스턴스에서 'index (_ : offsetBy :)'를 호출합니다.

그보고 String다음과 같은 방법이있다.

str.index(after: String.Index)
str.index(before: String.Index)
str.index(String.Index, offsetBy: String.IndexDistance)
str.index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)

처음에는 정말 혼란 스러웠 기 때문에 이해할 때까지 놀기 시작했습니다. 사용 방법을 보여주기 위해 아래에 답변을 추가하고 있습니다.


여기에 이미지 설명 입력

다음 예제는 모두

var str = "Hello, playground"

startIndexendIndex

  • startIndex 첫 번째 문자의 색인입니다.
  • endIndex마지막 문자 의 색인 입니다.

// character
str[str.startIndex] // H
str[str.endIndex]   // error: after last character

// range
let range = str.startIndex..<str.endIndex
str[range]  // "Hello, playground"

Swift 4의 단측 범위 를 사용하면 범위를 다음 형식 중 하나로 단순화 할 수 있습니다.

let range = str.startIndex...
let range = ..<str.endIndex

명확성을 위해 다음 예제에서는 전체 형식을 사용하지만 가독성을 위해 코드에서 단측 범위를 사용하는 것이 좋습니다.

after

에서와 같이 : index(after: String.Index)

  • after 주어진 색인 바로 뒤의 문자 색인을 참조합니다.

// character
let index = str.index(after: str.startIndex)
str[index]  // "e"

// range
let range = str.index(after: str.startIndex)..<str.endIndex
str[range]  // "ello, playground"

before

에서와 같이 : index(before: String.Index)

  • before 주어진 색인 바로 앞의 문자 색인을 참조합니다.

// character
let index = str.index(before: str.endIndex)
str[index]  // d

// range
let range = str.startIndex..<str.index(before: str.endIndex)
str[range]  // Hello, playgroun

offsetBy

에서와 같이 : index(String.Index, offsetBy: String.IndexDistance)

  • offsetBy값은 주어진 인덱스에서 긍정적 또는 부정적 개시 될 수있다. 그것은 유형이지만 String.IndexDistance, 당신은 그것에게를 제공 할 수 있습니다 Int.

// character
let index = str.index(str.startIndex, offsetBy: 7)
str[index]  // p

// range
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end
str[range]  // play

limitedBy

에서와 같이 : index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)

  • The limitedBy is useful for making sure that the offset does not cause the index to go out of bounds. It is a bounding index. Since it is possible for the offset to exceed the limit, this method returns an Optional. It returns nil if the index is out of bounds.

Example

// character
if let index = str.index(str.startIndex, offsetBy: 7, limitedBy: str.endIndex) {
    str[index]  // p
}

If the offset had been 77 instead of 7, then the if statement would have been skipped.

Why is String.Index needed?

It would be much easier to use an Int index for Strings. The reason that you have to create a new String.Index for every String is that Characters in Swift are not all the same length under the hood. A single Swift Character might be composed of one, two, or even more Unicode code points. Thus each unique String must calculate the indexes of its Characters.

Int 인덱스 확장 뒤에 이러한 복잡성을 숨기는 것이 가능하지만 그렇게하는 것을 꺼려합니다. 실제로 일어나고있는 일을 상기시키는 것이 좋습니다.


tableViewController 내부에 UITextView를 만듭니다. 나는 function : textViewDidChange를 사용한 다음 return-key-input을 확인했습니다. 리턴 키 입력이 감지되면 리턴 키 입력을 삭제하고 키보드를 닫습니다.

func textViewDidChange(_ textView: UITextView) {
    tableView.beginUpdates()
    if textView.text.contains("\n"){
        textView.text.remove(at: textView.text.index(before: textView.text.endIndex))
        textView.resignFirstResponder()
    }
    tableView.endUpdates()
}

Swift 4 완벽한 솔루션 :

OffsetIndexableCollection (Int 인덱스를 사용하는 문자열)

https://github.com/frogcjn/OffsetIndexableCollection-String-Int-Indexable-

참고 URL : https://stackoverflow.com/questions/39676939/how-does-string-index-work-in-swift

반응형