Convertir el range <Int> al range <String.Index>

La function siguiente que se proporciona a un NSString , elimina las tags HTML de esa cadena y devuelve el resultado también como un 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; } 

Estoy tratando de reescribir esto en Swift puro. Estoy enfrentando un problema con el tipo Range en Swift.

En la function de código original, la variable de range se declara de tipo NSRange . En mi versión no puedo hacer eso porque la línea sourceString.rangeOfString(HTMLTags, options: NSStringCompareOptions.RegularExpressionSearch) dentro del bucle while devuelve el tipo Range<String.Index> y me daría el error Can not convert the expression's type '() 'para escribir' NSRange ' .

Entonces declaré la variable como este var range = Range(start: 0, end: 0) pero ahora obtengo un par de errores nuevos.

No se puede convertir el tipo de expresión '()' en error tipo 'Rango' en la línea

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

Y 'Int' no es idéntico a 'String.Index' en la línea

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

Busqué una solución a esto y encontré esta publicación . Luego cambié la statement de la variable de range a esto.

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

¡Pero ahora tengo este nuevo error! Argumento adicional 'final' en llamada

No puedo encontrar una manera de resolver esto. ¿Alguien puede ayudar por favor?

Gracias.

El método Swift String rangeOfString() devuelve un Range? opcional Range? que no tiene una propiedad de location , pero se puede verificar con la vinculación condicional ( if let ).

Y si reemplaza el método stringByReplacingCharactersInRange() por el método Swift String replaceRange() (o en este caso simplemente por removeRange() ), entonces puede trabajar puramente con Range<Swift.Index> sin convertirlo a NSRange o 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; } 

Para personas como yo que realmente quieren get un 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)) } 

Debe hacer reference a la cadena en la que utilizará el range.

En Swift 2, string: String dada string: String y nsRange: NSRange , esto es

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

Pala de vapor de ejército suizo para suscripciones 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.pnetworkingecessor() x++ } return r } func -<T: IntegerType>(lhs: String.Index, rhs: T) -> String.Index { var r = lhs var x = rhs while x > 0 { r = r.pnetworkingecessor() 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) } } 

La esencia aquí

Convertir NSRange a la NSRange de Range<String.Index> swift

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