ChatGPT解决这个技术问题 Extra ChatGPT

How do you use String.substringWithRange? (or, how do Ranges work in Swift?)

I have not yet been able to figure out how to get a substring of a String in Swift:

var str = “Hello, playground”
func test(str: String) -> String {
 return str.substringWithRange( /* What goes here? */ )
}
test (str)

I'm not able to create a Range in Swift. Autocomplete in the Playground isn’t super helpful - this is what it suggests:

return str.substringWithRange(aRange: Range<String.Index>)

I haven't found anything in the Swift Standard Reference Library that helps. Here was another wild guess:

return str.substringWithRange(Range(0, 1))

And this:

let r:Range<String.Index> = Range<String.Index>(start: 0, end: 2)
return str.substringWithRange(r)

I've seen other answers (Finding index of character in Swift String) that seem to suggest that since String is a bridge type for NSString, the "old" methods should work, but it's not clear how - e.g., this doesn't work either (doesn't appear to be valid syntax):

let x = str.substringWithRange(NSMakeRange(0, 3))

Thoughts?

What do you mean when you say the last example doesn't work? Does it cause an error or return an unexpected value?
Please dupe rdar://17158813 requesting subscript notation openradar.appspot.com/radar?id=6373877630369792

m
matt---

You can use the substringWithRange method. It takes a start and end String.Index.

var str = "Hello, playground"
str.substringWithRange(Range<String.Index>(start: str.startIndex, end: str.endIndex)) //"Hello, playground"

To change the start and end index, use advancedBy(n).

var str = "Hello, playground"
str.substringWithRange(Range<String.Index>(start: str.startIndex.advancedBy(2), end: str.endIndex.advancedBy(-1))) //"llo, playgroun"

You can also still use the NSString method with NSRange, but you have to make sure you are using an NSString like this:

let myNSString = str as NSString
myNSString.substringWithRange(NSRange(location: 0, length: 3))

Note: as JanX2 mentioned, this second method is not safe with unicode strings.


Yeah. For now I'd keep on bridging to NSString when necessary. It seems Swift's String is still incomplete
This is not safe! You are assuming that indexes into String and NSString are interchangeable. That is NOT the case. Indexes into a String refer to Unicode code points while indexes into an NSString refer to UTF-16 code units! Try it with emoji.
Please note that Indexes into a String do NOT refer to Unicode code points anymore. Think of them as referencing user-perceived characters.
So what's the right answer here? Calling advance means we have to iterate the whole way through a possibly long string. But forming an NSRange and using NSString explicitly is dangerous? What's left?
Thanks, m8. This transition to Swift is kind of messy after 4 years only doing Objective-C.
W
Warif Akhand Rishi

Swift 2

Simple

let str = "My String"
let subStr = str[str.startIndex.advancedBy(3)...str.startIndex.advancedBy(7)]
//"Strin"

Swift 3

let startIndex = str.index(str.startIndex, offsetBy: 3)
let endIndex = str.index(str.startIndex, offsetBy: 7)

str[startIndex...endIndex]       // "Strin"
str.substring(to: startIndex)    // "My "
str.substring(from: startIndex)  // "String"

Swift 4

substring(to:) and substring(from:) are deprecated in Swift 4.

String(str[..<startIndex])    // "My "
String(str[startIndex...])    // "String"
String(str[startIndex...endIndex])    // "Strin"

THIS. So confusing that you have to find your index before you can use it. No idea why it took me so long to realise, but thanks for your contribution to human kind.
In swift 4 substring operations return an instance of the Substring type, instead of String. Need to convert the result to a String for long-term storage. let newString = String(substring)
M
Mabedan

NOTE: @airspeedswift makes some very insightful points on the trade-offs of this approach, particularly the hidden performance impacts. Strings are not simple beasts, and getting to a particular index may take O(n) time, which means a loop that uses a subscript can be O(n^2). You have been warned.

You just need to add a new subscript function that takes a range and uses advancedBy() to walk to where you want:

import Foundation

extension String {
    subscript (r: Range<Int>) -> String {
        get {
            let startIndex = self.startIndex.advancedBy(r.startIndex)
            let endIndex = startIndex.advancedBy(r.endIndex - r.startIndex)

            return self[Range(start: startIndex, end: endIndex)]
        }
    }
}

var s = "Hello, playground"

println(s[0...5]) // ==> "Hello,"
println(s[0..<5]) // ==> "Hello"

(This should definitely be part of the language. Please dupe rdar://17158813)

For fun, you can also add a + operator onto the indexes:

func +<T: ForwardIndex>(var index: T, var count: Int) -> T {
  for (; count > 0; --count) {
    index = index.succ()
  }
  return index
}

s.substringWithRange(s.startIndex+2 .. s.startIndex+5)

(I don't know yet if this one should be part of the language or not.)


We should probably work with String.Index instead of integer indexes as much as possible for performance reasons. Every conversion from an integer index into a String.Index needs to process the string to seek.
@AndrewDunn This is not premature optimization. Each conversion from an integer index into a String.Index is O(n), not O(1)! Please read the comments for advance<T>(…) in the Swift namespace.
The whole of the String implementation is done using String.Index. In this case it's not as much optimization as it is keeping everything straightforward. Having to juggle between int and String.Index back and forth everywhere will leads to a mess.
@chakrit Only if indexes you need to use aren't already integers (instead of being String.Indexes) which is often the case. Than you can just wish all those string handling methods were working with Ints. And you are forced to conver it to String.Indexes which leads to the mess you mentioned.
The interested reader should give a look at ExSwift github.com/pNre/ExSwift
G
Glenn Posadas

At the time I'm writing, no extension is perfectly Swift 4.2 compatible, so here is one that covers all the needs I could think of:

extension String {
    func substring(from: Int?, to: Int?) -> String {
        if let start = from {
            guard start < self.count else {
                return ""
            }
        }

        if let end = to {
            guard end >= 0 else {
                return ""
            }
        }

        if let start = from, let end = to {
            guard end - start >= 0 else {
                return ""
            }
        }

        let startIndex: String.Index
        if let start = from, start >= 0 {
            startIndex = self.index(self.startIndex, offsetBy: start)
        } else {
            startIndex = self.startIndex
        }

        let endIndex: String.Index
        if let end = to, end >= 0, end < self.count {
            endIndex = self.index(self.startIndex, offsetBy: end + 1)
        } else {
            endIndex = self.endIndex
        }

        return String(self[startIndex ..< endIndex])
    }

    func substring(from: Int) -> String {
        return self.substring(from: from, to: nil)
    }

    func substring(to: Int) -> String {
        return self.substring(from: nil, to: to)
    }

    func substring(from: Int?, length: Int) -> String {
        guard length > 0 else {
            return ""
        }

        let end: Int
        if let start = from, start > 0 {
            end = start + length - 1
        } else {
            end = length - 1
        }

        return self.substring(from: from, to: end)
    }

    func substring(length: Int, to: Int?) -> String {
        guard let end = to, end > 0, length > 0 else {
            return ""
        }

        let start: Int
        if let end = to, end - length > 0 {
            start = end - length + 1
        } else {
            start = 0
        }

        return self.substring(from: start, to: to)
    }
}

And then, you can use:

let string = "Hello,World!"

string.substring(from: 1, to: 7)gets you: ello,Wo

string.substring(to: 7)gets you: Hello,Wo

string.substring(from: 3)gets you: lo,World!

string.substring(from: 1, length: 4)gets you: ello

string.substring(length: 4, to: 7)gets you: o,Wo

Updated substring(from: Int?, length: Int) to support starting from zero.


How does this handle emoji and extended grapheme clusters? (I should test it out myself but it's not convenient at the moment.)
@Suragch It handles it OK: "Hello😇😍😘😎📸📀💾∝ℵℶ≹".substring(from: 4, to: 14) gives us: o😇😍😘😎📸📀💾∝ℵℶ
Those look like normal characters, though. Try using emoji like 👩‍👩‍👧‍👦 or 🇨🇦🇺🇸🇲🇽
p
phnmnn

SWIFT 2.0

simple:

let myString = "full text container"
let substring = myString[myString.startIndex..<myString.startIndex.advancedBy(3)] // prints: ful

SWIFT 3.0

let substring = myString[myString.startIndex..<myString.index(myString.startIndex, offsetBy: 3)] // prints: ful

SWIFT 4.0

Substring operations return an instance of the Substring type, instead of String.

let substring = myString[myString.startIndex..<myString.index(myString.startIndex, offsetBy: 3)] // prints: ful

// Convert the result to a String for long-term storage.
let newString = String(substring)

No longer compatible with Swift 3 as of Xcode 8 beta 6, sadly
Works for me. Xcode 8, Swift 3. Not beta on Mac OS Sierra. text[text.startIndex..<text.index(text.startIndex, offsetBy: 2)]
C
Community

It is much more simple than any of the answers here, once you find the right syntax.

I want to take away the [ and ]

let myString = "[ABCDEFGHI]"
let startIndex = advance(myString.startIndex, 1) //advance as much as you like
let endIndex = advance(myString.endIndex, -1)
let range = startIndex..<endIndex
let myNewString = myString.substringWithRange( range )

result will be "ABCDEFGHI" the startIndex and endIndex could also be used in

let mySubString = myString.substringFromIndex(startIndex)

and so on!

PS: As indicated in the remarks, there are some syntax changes in swift 2 which comes with xcode 7 and iOS9!

Please look at this page


Yes, I had the same issues with the debugger not showing the correct string several time?
i have a string like this /Date(147410000000)/. How can i get value instead of specifying the index. I need to get the value using rangeOfString("(") and rangeOfString(")"). The result should be 147410000000. Hoe can i get that
That is not so hard:var str = "/Date(147410000000)/." var range = str.rangeOfString( "(" )!.endIndex..
since Xcode 7 beta 6 advance(myString.endIndex, -1) syntax has changed to myString.endIndex.advancedBy(-1)
J
Joris Kluivers

For example to find the first name (up to the first space) in my full name:

let name = "Joris Kluivers"

let start = name.startIndex
let end = find(name, " ")

if end {
    let firstName = name[start..end!]
} else {
    // no space found
}

start and end are of type String.Index here and are used to create a Range<String.Index> and used in the subscript accessor (if a space is found at all in the original string).

It's hard to create a String.Index directly from an integer position as used in the opening post. This is because in my name each character would be of equal size in bytes. But characters using special accents in other languages could have used several more bytes (depending on the encoding used). So what byte should the integer refer to?

It's possible to create a new String.Index from an existing one using the methods succ and pred which will make sure the correct number of bytes are skipped to get to the next code point in the encoding. However in this case it's easier to search for the index of the first space in the string to find the end index.


C
Community

Since String is a bridge type for NSString, the "old" methods should work, but it's not clear how - e.g., this doesn't work either (doesn't appear to be valid syntax): let x = str.substringWithRange(NSMakeRange(0, 3))

To me, that is the really interesting part of your question. String is bridged to NSString, so most NSString methods do work directly on a String. You can use them freely and without thinking. So, for example, this works just as you expect:

// delete all spaces from Swift String stateName
stateName = stateName.stringByReplacingOccurrencesOfString(" ", withString:"")

But, as so often happens, "I got my mojo workin' but it just don't work on you." You just happened to pick one of the rare cases where a parallel identically named Swift method exists, and in a case like that, the Swift method overshadows the Objective-C method. Thus, when you say str.substringWithRange, Swift thinks you mean the Swift method rather than the NSString method — and then you are hosed, because the Swift method expects a Range<String.Index>, and you don't know how to make one of those.

The easy way out is to stop Swift from overshadowing like this, by casting explicitly:

let x = (str as NSString).substringWithRange(NSMakeRange(0, 3))

Note that no significant extra work is involved here. "Cast" does not mean "convert"; the String is effectively an NSString. We are just telling Swift how to look at this variable for purposes of this one line of code.

The really weird part of this whole thing is that the Swift method, which causes all this trouble, is undocumented. I have no idea where it is defined; it is not in the NSString header and it's not in the Swift header either.


However, I suggest filing a bug. Apple should "fish or cut bait" - either give us a way to construct a Range<String.Index>, or get this undocumented method out of our way.
Damn - this is useful. Despite what the documentation says, I didn't understand what was going wrong until I read this. Now sorted :)
N
Nate Cook

The short answer is that this is really hard in Swift right now. My hunch is that there is still a bunch of work for Apple to do on convenience methods for things like this.

String.substringWithRange() is expecting a Range<String.Index> parameter, and as far as I can tell there isn't a generator method for the String.Index type. You can get String.Index values back from aString.startIndex and aString.endIndex and call .succ() or .pred() on them, but that's madness.

How about an extension on the String class that takes good old Ints?

extension String {
    subscript (r: Range<Int>) -> String {
        get {
            let subStart = advance(self.startIndex, r.startIndex, self.endIndex)
            let subEnd = advance(subStart, r.endIndex - r.startIndex, self.endIndex)
            return self.substringWithRange(Range(start: subStart, end: subEnd))
        }
    }
    func substring(from: Int) -> String {
        let end = countElements(self)
        return self[from..<end]
    }
    func substring(from: Int, length: Int) -> String {
        let end = from + length
        return self[from..<end]
    }
}

let mobyDick = "Call me Ishmael."
println(mobyDick[8...14])             // Ishmael

let dogString = "This 🐶's name is Patch."
println(dogString[5..<6])               // 🐶
println(dogString[5...5])              // 🐶
println(dogString.substring(5))        // 🐶's name is Patch.
println(dogString.substring(5, length: 1))   // 🐶

Update: Swift beta 4 resolves the issues below!

As it stands [in beta 3 and earlier], even Swift-native strings have some issues with handling Unicode characters. The dog icon above worked, but the following doesn't:

let harderString = "1:1️⃣"
for character in harderString {
    println(character)
}

Output:

1
:
1
️
⃣

It's odd, the core Swift classes just seem to lack a lot of basic functions. I can't think Apple wants us to continually reference Foundation classes to perform simple tasks.
Totally. Keep in mind that Swift was basically developed in the dark, and everyone has a different definition of "simple tasks" - I bet we see some quick iteration on these issues.
@JanX2 - Thanks, you're totally right. The seamless bridging with NSString made me think I was using only Swift-native String methods, since I wasn't using any myString as NSString calls.
There are some Unicode bugs in Swift-native string handling right now, too: see my note at the end.
@NateCook Can you please file a radar for that issue?
C
Claudio Guirunas

In new Xcode 7.0 use

//: Playground - noun: a place where people can play

import UIKit

var name = "How do you use String.substringWithRange?"
let range = name.startIndex.advancedBy(0)..<name.startIndex.advancedBy(10)
name.substringWithRange(range)

//OUT:

https://i.stack.imgur.com/1wYAl.png


.advancedBy(0) isn't necessary for startIndex.
C
ChikabuZ

You can use this extensions to improve substringWithRange

Swift 2.3

extension String
{   
    func substringWithRange(start: Int, end: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if end < 0 || end > self.characters.count
        {
            print("end index \(end) out of bounds")
            return ""
        }
        let range = Range(start: self.startIndex.advancedBy(start), end: self.startIndex.advancedBy(end))
        return self.substringWithRange(range)
    }

    func substringWithRange(start: Int, location: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if location < 0 || start + location > self.characters.count
        {
            print("end index \(start + location) out of bounds")
            return ""
        }
        let range = Range(start: self.startIndex.advancedBy(start), end: self.startIndex.advancedBy(start + location))
        return self.substringWithRange(range)
    }
}

Swift 3

extension String
{
    func substring(start: Int, end: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if end < 0 || end > self.characters.count
        {
            print("end index \(end) out of bounds")
            return ""
        }
        let startIndex = self.characters.index(self.startIndex, offsetBy: start)
        let endIndex = self.characters.index(self.startIndex, offsetBy: end)
        let range = startIndex..<endIndex

        return self.substring(with: range)
    }

    func substring(start: Int, location: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if location < 0 || start + location > self.characters.count
        {
            print("end index \(start + location) out of bounds")
            return ""
        }
        let startIndex = self.characters.index(self.startIndex, offsetBy: start)
        let endIndex = self.characters.index(self.startIndex, offsetBy: start + location)
        let range = startIndex..<endIndex

        return self.substring(with: range)
    }
}

Usage:

let str = "Hello, playground"

let substring1 = str.substringWithRange(0, end: 5) //Hello
let substring2 = str.substringWithRange(7, location: 10) //playground

U
Umang Kothari

Sample Code for how to get substring in Swift 2.0

(i) Substring from starting index

Input:-

var str = "Swift is very powerful language!"
print(str)

str = str.substringToIndex(str.startIndex.advancedBy(5))
print(str)

Output:-

Swift is very powerful language!
Swift

(ii) Substring from particular index

Input:-

var str = "Swift is very powerful language!"
print(str)

str = str.substringFromIndex(str.startIndex.advancedBy(6)).substringToIndex(str.startIndex.advancedBy(2))
print(str)

Output:-

Swift is very powerful language!
is

I hope it will help you!


O
Oliver Dixon

Easy solution with little code.

Make an extension that includes basic subStringing that nearly all other languages have:

extension String {
    func subString(start: Int, end: Int) -> String {
        let startIndex = self.index(self.startIndex, offsetBy: start)
        let endIndex = self.index(startIndex, offsetBy: end)

        let finalString = self.substring(from: startIndex)
        return finalString.substring(to: endIndex)
    }
}

Simply call this with

someString.subString(start: 0, end: 6)

The 'end' parameter actually means length here so I think it should be renamed to that.
I think using length is rather confusing. It's in fact the 'end' of where you'd like the subString to be, not the actual length of the subStrings result.
p
patrykens

This works in my playground :)

String(seq: Array(str)[2...4])

Actually this is more efficient than calling advance
It's not working in my Xcode 7 (Swift 2) playground, but this does... 'var str = "Hello, playground"' String(Array(str.characters)[7]) // "p" String(Array(str.characters)[7...10]) // "play" String(Array(str.characters)[7..<10]) // "pla"
F
Firo

Updated for Xcode 7. Adds String extension:

Use:

var chuck: String = "Hello Chuck Norris"
chuck[6...11] // => Chuck

Implementation:

extension String {

    /**
     Subscript to allow for quick String substrings ["Hello"][0...1] = "He"
     */
    subscript (r: Range<Int>) -> String {
        get {
            let start = self.startIndex.advancedBy(r.startIndex)
            let end = self.startIndex.advancedBy(r.endIndex - 1)
            return self.substringWithRange(start..<end)
        }
    }

}

P
Peter Roberts

try this in playground

var str:String = "Hello, playground"

let range = Range(start:advance(str.startIndex,1), end: advance(str.startIndex,8))

it will give you "ello, p"

However where this gets really interesting is that if you make the last index bigger than the string in playground it will show any strings that you defined after str :o

Range() appears to be a generic function so that it needs to know the type it is dealing with.

You also have to give it the actual string your interested in playgrounds as it seems to hold all stings in a sequence one after another with their variable name afterwards.

So

var str:String = "Hello, playground"

var str2:String = "I'm the next string"

let range = Range(start:advance(str.startIndex,1), end: advance(str.startIndex,49))

gives "ello, playground�str���I'm the next string�str2�"

works even if str2 is defined with a let

:)


I agree it is verbose compared to Objective-C, however it all fits on one line which is a bonus.
Well there is still the one line missing that actually prints out the substring given the range you computed. I like some of the other solutions that create String class extensions using your logic, but in an extension. That is ultimately the solution I went with.
They've fixed the bug where you can go beyond the end of the string. Now you can only put in a value up till str.endIndex
i
ipraba

Rob Napier had already given a awesome answer using subscript. But i felt one drawback in that as there is no check for out of bound conditions. This can tend to crash. So i modified the extension and here it is

extension String {
    subscript (r: Range<Int>) -> String? { //Optional String as return value
        get {
            let stringCount = self.characters.count as Int
            //Check for out of boundary condition
            if (stringCount < r.endIndex) || (stringCount < r.startIndex){
                return nil
            }
            let startIndex = self.startIndex.advancedBy(r.startIndex)

            let endIndex = self.startIndex.advancedBy(r.endIndex - r.startIndex)

            return self[Range(start: startIndex, end: endIndex)]
        }
    }
}

Output below

var str2 = "Hello, World"

var str3 = str2[0...5]
//Hello,
var str4 = str2[0..<5]
//Hello
var str5 = str2[0..<15]
//nil

So i suggest always to check for the if let

if let string = str[0...5]
{
    //Manipulate your string safely
}

You've got a bug there - endIndex should be startIndex advanced by endIndex alone, not the distance between indices.
S
Sandu

In Swift3

For ex: a variable "Duke James Thomas", we need to get "James".

let name = "Duke James Thomas"
let range: Range<String.Index> = name.range(of:"James")!
let lastrange: Range<String.Index> = img.range(of:"Thomas")!
var middlename = name[range.lowerBound..<lstrange.lowerBound]
print (middlename)

A
Albert Bori

Taking a page from Rob Napier, I developed these Common String Extensions, two of which are:

subscript (r: Range<Int>) -> String
{
    get {
        let startIndex = advance(self.startIndex, r.startIndex)
        let endIndex = advance(self.startIndex, r.endIndex - 1)

        return self[Range(start: startIndex, end: endIndex)]
    }
}

func subString(startIndex: Int, length: Int) -> String
{
    var start = advance(self.startIndex, startIndex)
    var end = advance(self.startIndex, startIndex + length)
    return self.substringWithRange(Range<String.Index>(start: start, end: end))
}

Usage:

"Awesome"[3...7] //"some"
"Awesome".subString(3, length: 4) //"some"

You can use Range instead of Range<String.Index> thanks to type inference.
C
Community

This is how you get a range from a string:

var str = "Hello, playground"

let startIndex = advance(str.startIndex, 1)
let endIndex = advance(startIndex, 8)
let range = startIndex..<endIndex
let substr = str[range] //"ello, pl"

The key point is that you are passing a range of values of type String.Index (this is what advance returns) instead of integers.

The reason why this is necessary, is that strings in Swift don't have random access (because of variable length of Unicode characters basically). You also can't do str[1]. String.Index is designed to work with their internal structure.

You can create an extension with a subscript though, that does this for you, so you can just pass a range of integers (see e.g. Rob Napier's answer).


f
funct7

I tried to come up with something Pythonic.

All the subscripts here are great, but the times I really need something simple is usually when I want to count from back, e.g. string.endIndex.advancedBy(-1)

It supports nil values, for both start and end index, where nil would mean index at 0 for start, string.characters.count for end.

extension String {
    var subString: (Int?) -> (Int?) -> String {
        return { (start) in
            { (end) in
                let startIndex = start ?? 0 < 0 ? self.endIndex.advancedBy(start!) : self.startIndex.advancedBy(start ?? 0)
                let endIndex = end ?? self.characters.count < 0 ? self.endIndex.advancedBy(end!) : self.startIndex.advancedBy(end ?? self.characters.count)

                return startIndex > endIndex ? "" : self.substringWithRange(startIndex ..< endIndex)
            }
        }
    }
}

let dog = "Dog‼🐶"
print(dog.subString(nil)(-1)) // Dog!!

EDIT

A more elegant solution:

public extension String {
    struct Substring {
        var start: Int?
        var string: String

        public subscript(end: Int?) -> String {
            let startIndex = start ?? 0 < 0 ? string.endIndex.advancedBy(start!) : string.startIndex.advancedBy(start ?? 0)
            let endIndex = end ?? string.characters.count < 0 ? string.endIndex.advancedBy(end!) : string.startIndex.advancedBy(end ?? string.characters.count)

            return startIndex > endIndex ? "" : string.substringWithRange(startIndex ..< endIndex)
        }
    }

    public subscript(start: Int?) -> Substring {
        return Substring(start: start, string: self)
    }
}

let dog = "Dog‼🐶"
print(dog[nil][-1]) // Dog!!

J
Johannes

First create the range, then the substring. You can use fromIndex..<toIndex syntax like so:

let range = fullString.startIndex..<fullString.startIndex.advancedBy(15) // 15 first characters of the string
let substring = fullString.substringWithRange(range)

H
Hardik Thakkar

here is a example to get video-Id only .i.e (6oL687G0Iso) from the whole URL in swift

let str = "https://www.youtube.com/watch?v=6oL687G0Iso&list=PLKmzL8Ib1gsT-5LN3V2h2H14wyBZTyvVL&index=2"
var arrSaprate = str.componentsSeparatedByString("v=")
let start = arrSaprate[1]
let rangeOfID = Range(start: start.startIndex,end:start.startIndex.advancedBy(11))
let substring = start[rangeOfID]
print(substring)

S
Svitlana
let startIndex = text.startIndex
var range = startIndex.advancedBy(1) ..< text.endIndex.advancedBy(-4)
let substring = text.substringWithRange(range)

Full sample you can see here


s
swiftmb

http://www.learnswiftonline.com/reference-guides/string-reference-guide-for-swift/ shows that this works well:

var str = "abcd"
str = str.substringToIndex(1)

Playground execution failed: error: :23:5: error: type 'String.Index' does not conform to protocol 'IntegerLiteralConvertible' str = str.substringToIndex(1) ^
s
sittisal

Well, I had the same issue and solved with the "bridgeToObjectiveC()" function:

var helloworld = "Hello World!"
var world = helloworld.bridgeToObjectiveC().substringWithRange(NSMakeRange(6,6))
println("\(world)") // should print World!

Please note that in the example, substringWithRange in conjunction with NSMakeRange take the part of the string starting at index 6 (character "W") and finishing at index 6 + 6 positions ahead (character "!")

Cheers.


I hate this, but it is the only thing that seems to be working for me in Beta 4.
W
William Falcon

You can use any of the substring methods in a Swift String extension I wrote https://bit.ly/JString.

var string = "hello"
var sub = string.substringFrom(3) // or string[3...5]
println(sub)// "lo"

j
joslinm

If you have an NSRange, bridging to NSString works seamlessly. For example, I was doing some work with UITextFieldDelegate and I quickly wanted to compute the new string value when it asked if it should replace the range.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let newString = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
    println("Got new string: ", newString)
}

B
Bartłomiej Semańczyk

Simple extension for String:

extension String {

    func substringToIndex(index: Int) -> String {
        return self[startIndex...startIndex.advancedBy(min(index, characters.count - 1))]
    }
}

J
Jiachen Ren

If you don't care about performance... this is probably the most concise solution in Swift 4

extension String {
    subscript(range: CountableClosedRange<Int>) -> String {
        return enumerated().filter{$0.offset >= range.first! && $0.offset < range.last!}
            .reduce(""){$0 + String($1.element)}
    }
}

It enables you to do something like this:

let myStr = "abcd"
myStr[0..<2] // produces "ab"