New Life of Strings in Swift: Goodbye, substring, Hello, Slicing

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

How to Stop Fearing deprecated and Embrace Slicing in Swift



If you've ever written code in Swift and tried to cut out part of a string, you've likely encountered this frightening message: 'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator. Sounds like a death sentence? In reality, it's an invitation to a new, safer, and more powerful world of working with strings. Let's figure out what happened, why Apple decided to change the familiar API, and how to properly "slice" strings in Swift 4 and newer.



Why did substring become a thing of the past?



The good old substring(to:) worked, but it was... not very smart. It returned a new Substring object, which was essentially just a "window" into the original string. This led to confusion: you thought you were working with an independent string, but in reality, you were holding a reference to the old memory. In Swift 4, they decided to clean things up: now all substring operations return the Substring type, and to get a full-fledged string, you need to explicitly convert the result. Sounds more complicated? In practice, it's much clearer and safer.



Meet: String slicing subscript



The new approach uses subscripts and ranges. Instead of the substring(to:), substring(from:), and substring(with:) methods, you now write code that looks like working with arrays. Here's a basic analogy:



let fullString = "Привет, мир!"// Old way (deprecated)// let oldResult = fullString.substring(to: fullString.index(fullString.startIndex, offsetBy: 6))

// New waylet newResult = fullString[..<fullString.index(fullString.startIndex, offsetBy: 6)]print(newResult) // "Привет"


See the ..< operator? That's the very partial range from operator — a partial range "from the beginning up to, but not including, the specified index". Powerful? You bet.



The Three Pillars of the New Approach: from, to, through



Let's break down the three main scenarios that the substring methods used to cover.



1. substring(to:) → prefix(upTo:) or a partial range

Want to take everything up to a certain index? Use ..< (half-open range) or the prefix(upTo:) method:



let str = "Hello, Swift"let index = str.firstIndex(of: ",") ?? str.endIndex

// Option using subscriptlet result1 = str[..<index]print(result1) // "Hello"

// Option using methodlet result2 = str.prefix(upTo: index)print(result2) // "Hello"


2. substring(from:) → suffix(from:) or a partial range

Need to take everything from an index to the end? Use ... (closed range) with the start omitted:



let startIndex = str.index(str.startIndex, offsetBy: 7)let result3 = str[startIndex...]print(result3) // "Swift"

// Or via methodlet result4 = str.suffix(from: startIndex)print(result4) // "Swift"


3. substring(with:) → a regular range

Want to extract a specific piece? Just specify the range:



let range = str.index(str.startIndex, offsetBy: 7)..<str.endIndexlet result5 = str[range]print(result5) // "Swift"

// Or via closed rangelet closedRange = str.index(str.startIndex, offsetBy: 7)...str.index(before: str.endIndex)let result6 = str[closedRange]print(result6) // "Swift"


Note: all these operations return Substring, not String. If you need a full-fledged string, simply wrap the result in String():



let newString = String(result1)print(type(of: newString)) // String


What about prefix and suffix? They aren't deprecated!



Yes, the prefix(_:), suffix

Blogs

Book Recommendations