4

I want do call the method "deleteCharactersInRange" but it doesn't work.

This is an excerpt from Apples Documentation:

Swift

func deleteCharactersInRange(_ aRange: NSRange)

    var day = ""

    let stringRange:NSRange = NSMakeRange(0, 4)
    day = day.deleteCharacterInRange(stringRange)


    // I've also tried this, because in the Documentation 
    // I can't see wether the method is void or returns a String

    day.deleteCharacterInRange(stringRange)

I get this error message:

'String' does not have a member named 'deleteCharactersInRange'

Community
  • 1
  • 1
Codey
  • 1,131
  • 2
  • 15
  • 34

3 Answers3

13

The method you're citing belongs to NSMutableString. But since you're using Swift and haven't explicitly created one, you get a Swift String.

If you want to operate on Swift String, you need to use str.removeRange and the rather awkward to use Range:

var str = "Hello, playground"
str.removeRange(Range<String.Index>(start: str.startIndex, end:advance(str.startIndex, 7)))
// "playground"
DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • Thank you, but what does this "Range" mean/do? Is this also a kind of method and if yes what kind? – Codey Nov 22 '14 at 17:49
  • To break down this answer..., `Range(/*stuff*/)` is equivalent (roughly) to the `NSMakeRange` function. It's an initializer for the Swift `Range` struct. – nhgrif Nov 22 '14 at 17:50
  • `day.removeRange(Range(start: 0, end: 4))` This code does not work, I get the error message "Extra argument 'end' in call" – Codey Nov 22 '14 at 17:51
  • 2
    You have to use the `str.startIndex` and the `advance` function. – nhgrif Nov 22 '14 at 17:52
  • end:advance(day.startIndex, 4) – Leo Dabus Nov 22 '14 at 17:53
  • Ok and what if I want the start not to be at the beginning, but lets say at Index 4? – Codey Nov 22 '14 at 17:54
  • `let startIndex = advance(str.startIndex, 4)` – nhgrif Nov 22 '14 at 18:04
  • 3
    You don't even need to call the constructor of `Range` directly. Instead you can do something like: `str.removeRange(str.startIndex.. –  Nov 22 '14 at 18:05
  • but what the heck is "startIndex"? Is it always the character at index 0? If so then why the heck do they have this gobbledegook syntax? – CommaToast Mar 20 '16 at 18:45
  • @CommaToast: Yes, it's always the first character. Correctly assigning a number to a character position is tricky and error-prone, which is why Swift doesn't do this and instead uses a _Index_ class/struct. See the [Swift blog entry about Strings in Swift 2.0](https://developer.apple.com/swift/blog/?id=30) why it's tricky; at least look at the table near the end. For more gory details, see the [Swift String documentation, section _String Indices_](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html). – DarkDust Mar 20 '16 at 19:05
4

In light of DarkDust's answer, we can make a very Swift-like extension that will make removeRange easier to use:

extension String {
    mutating func deleteCharactersInRange(range: NSRange) {
        let startIndex = self.startIndex.advancedBy(range.location)
        let length = range.length
        self.removeRange(startIndex ..< startIndex.advancedBy(length))
    }
}

Now you can use it as such:

let range = NSMakeRange(0,4)
var day = "Tuesday"
day.deleteCharactersInRange(range) // day = "day"
Ryan Brodie
  • 6,554
  • 8
  • 40
  • 57
nhgrif
  • 61,578
  • 25
  • 134
  • 173
  • Ok, my problem was that I thought Apple removed all of this "Mutable-" thing and instead use var and let. – Codey Nov 22 '14 at 17:47
  • @Codey See my most recent edit. Use the String extension at the top of my answer rather than the one at the bottom. – nhgrif Nov 22 '14 at 17:48
  • In the first Code block line 3. Does the self refer to the string that is calling the function? And what does the keyword "mutating" do for the function? – Codey Nov 22 '14 at 18:02
  • Yes. The word `mutating` allows a function to modify `self`. `struct`'s functions aren't allowed to modify `self` unless they are marked as `mutating`. – nhgrif Nov 22 '14 at 18:04
  • Thank you! One more question: Where do I declare an extension so that all of the classes in my project can make use of it? – Codey Nov 22 '14 at 18:22
  • 1
    In Swift, anywhere. For code cleanliness and organization, I'd probably just create a new file though and put it there by itself (plus other useful String extensions you might have or use) – nhgrif Nov 22 '14 at 18:22
3

Update for Swift 3

In Swift 3 it is required to use the range operators a..<b or a...b.

var aString = "This is just the beginning"
str.removeRange(Range<String.Index>(str.startIndex ..< str.startIndex.advancedBy(10)))

or even more concise

aString.removeRange(aString.startIndex..<aString.startIndex.advancedBy(10))
ff10
  • 3,046
  • 1
  • 32
  • 55