Преобразовать диапазон<Int> в диапазон<String.Index>

Приведенная ниже функция NSString удаляет теги HTML из этой строки и возвращает результат также в виде NSString,

private func removeHTMLTags(source: NSString) -> NSString {
    var range = NSMakeRange(0, 0)
    let HTMLTags = "<[^>]*>"
    var sourceString = source

    while sourceString.rangeOfString(HTMLTags, options: NSStringCompareOptions.RegularExpressionSearch).location != NSNotFound {
        range = sourceString.rangeOfString(HTMLTags, options: NSStringCompareOptions.RegularExpressionSearch)
        sourceString = sourceString.stringByReplacingCharactersInRange(range, withString: "")
    }
    return sourceString;
}

Я пытаюсь переписать это на чистом Свифте. У меня проблема с Range введите Свифт.

В оригинальной функции кода range объявлена ​​переменная типа NSRange, В моей версии я не могу этого сделать, потому что линия sourceString.rangeOfString(HTMLTags, options: NSStringCompareOptions.RegularExpressionSearch) внутри цикла while возвращает тип Range<String.Index> и это дало бы мне ошибку. Невозможно преобразовать тип выражения '()' в тип 'NSRange'.

Итак, я объявил переменную, как это var range = Range(start: 0, end: 0) но теперь я получаю пару новых ошибок.

Невозможно преобразовать тип выражения '()' в тип ошибки 'Range' в строке

range = sourceString.rangeOfString(HTMLTags, options: NSStringCompareOptions.RegularExpressionSearch)

И "Int" не совпадает с "String.Index" в строке

sourceString = sourceString.stringByReplacingCharactersInRange(range, withString: "")

Я искал решение для этого и наткнулся на этот пост. Затем я изменил range объявление переменной к этому.

var range = Range<String.Index>(start: 0, end: 0)

Но я получаю эту новую ошибку сейчас! Дополнительный аргумент "конец" в вызове

Я не могу найти способ решить эту проблему. Может кто-нибудь помочь, пожалуйста?

Спасибо.

5 ответов

Решение

Свифт String метод rangeOfString() возвращает необязательный Range? который не имеет location свойство, но можно проверить с помощью условного связывания (if let).

И если вы замените NSString метод stringByReplacingCharactersInRange()Свифт String метод replaceRange() (или в этом случае просто removeRange()) тогда вы можете работать чисто с Range<Swift.Index>без преобразования его в NSRange или же Range<Int>,

func removeHTMLTags(source : String) -> String {

    var sourceString = source
    let HTMLTags = "<[^>]*>"

    while let range = sourceString.rangeOfString(HTMLTags, options: .RegularExpressionSearch) {
        sourceString.removeRange(range)
    }

    return sourceString;
}

Для людей, как я, которые действительно хотят получить Range<String.Index>:

func convert(range: Range<Int>, string: String) -> Range<String.Index>
{
    return Range<String.Index>(start: advance(string.startIndex, range.startIndex),
                               end: advance(string.startIndex, range.endIndex))
}

Вам нужно ссылаться на строку, где вы будете использовать диапазон.

В Swift 2 дано string: String а также nsRange: NSRange, это

let range = Range(start: string.startIndex.advancedBy(nsRange.location),
    end: string.startIndex.advancedBy(nsRange.location+nsRange.length))

Перерабатывать NSRange в Range<String.Index> быстрая функция

func rangeWithString(string : String, range : NSRange) -> Range<String.Index> {
    return string.startIndex.advancedBy(range.location) ..< string.startIndex.advancedBy(range.location+range.length)
}

Швейцарская паровая лопата для String индексирование, NSRange, Range<Int|String.Index> преобразования

import Foundation

func +<T: IntegerType>(lhs: String.Index, rhs: T) -> String.Index {
    var r = lhs
    var x = rhs
    while x > 0 { // advance() won't work because IntegerType and String.Index are incompatible 
        r = r.successor()
        x--
    }
    while x < 0 {
        r = r.predecessor()
        x++
    }
    return r
}

func -<T: IntegerType>(lhs: String.Index, rhs: T) -> String.Index {
    var r = lhs
    var x = rhs
    while x > 0 {
        r = r.predecessor()
        x--
    }
    while x < 0 {
        r = r.successor()
        x++
    }
    return r
}

extension NSRange {
    init(range: Range<Int>) {
        location = range.startIndex
        length = range.endIndex - range.startIndex
    }

    var range: Range<Int> { return Range<Int>(start: location, end: location + length) }
}

extension String {
    var nsrange: NSRange { return NSMakeRange(0, count(self)) }

    var range: Range<Int> { return Range<Int>(start: 0, end: count(self)) }

    subscript (index: Int) -> String {
        return self[index...index]
    }

    subscript (index: Int) -> Character {
        return self[index] as Character
    }

    subscript (range: Range<String.Index>) -> String {
        return substringWithRange(range)
    }

    subscript (range: NSRange) -> String {
        return self[toStringRange(range)]
    }

    // allows "abcd"[0...1] // "ab"
    subscript (range: Range<Int>) -> String {
        return self[toStringRange(range)]
    }

    func toStringRange(range: NSRange) -> Range<String.Index> {
        return toStringRange(range.range)
    }

    func toStringRange(range: Range<Int>) -> Range<String.Index> {
        let start = startIndex + max(range.startIndex, 0)
        let end = startIndex + min(range.endIndex, count(self))
        return Range<String.Index>(start: start, end: end)
    }
}

Гист здесь

Другие вопросы по тегам