하나의 문자를 특정 index에 넣고 싶으면 insert(_:at:) 메소드를 사용하면 된다. 문자열을 넣고 싶은 경우에는 insert(contentsOf:at:) 메소드를 사용한다.
var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
// welcome의 값은 "hello!" 이다.
welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
// welcome의 값은 "hello there!"이다.
반대로 하나의 문자를 특정 index에서 지우고 싶을 땐 remove(at:) 을 특정 범위의 값들을 지우고 싶을 땐 removeSubrange(_:) 메소드를 사용한다.
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"
위의 4가지 메소드들은 String 뿐만이 아니라 RangeReplaceableCollection 프로토콜을 따르는 모든 타입에서 사용 할 수 있다. String, Array, Dictionary, Set등이 이에 해당한다.
문자열에서 문자열을 추출할때 subscript나 prefix같은 메소드를 사용하면. 그 결과는 다른 문자열이 아니라 Substring의 인스턴스입니다. Substring은 swift에서 String의 거의 모든 메소드들을 가지고 있다. 하지만 string과 다르게 substring은 짧게 저장할때만 사용해야합니다. 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은 substring을 구성하는 문자들이 저장된 메모리 공간이 있습니다.
string과 substring은 성능최적화면에서 다른점이 있는데, substring은 substring의 오리지널 string이 저장된 메모리나 다른 substring을 저장한 메모리를 다시 사용한다는 점 입니다.
(string도 비슷한 최적화를 가지지만, 두 string이 같은 메모리를 공유하면 같다고 봅니다)
이 성능 최적화는 다른 string이나 substring을 수정하는데에 성능에 영향을 주지 않는 역할을 합니다.
위에서 언급했듯이 substring은 길게 저장하는데에 적합하지 않은데, 그 이유는 substring이 사용되고 있는 한 substring의 original string은 메모리에서 사라지지 않기 때문입니다.
위의 코드 예시를 대입하면 String인 변수 greeting은 Hello, world! 라는 값을 메모리에 저장하고 있고, Substring인 변수 beginning은 orginal String인 greeting의 메모리를 참조하고 있습니다. 하지만 새로만든 newString은 greeting이나 beginning과 다른 새로운 메모리를 사용합니다.