2014-11-26 12 views
9

La funzione seguente fornita di NSString rimuove i tag HTML da quella stringa e restituisce il risultato anche come NSString.Converti intervallo <Int> nell'intervallo <String.Index>

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; 
} 

Sto provando a riscrivere questo in puro Swift. Sto affrontando un problema con il tipo Range in Swift.

Nella funzione di codice originale, la variabile range è dichiarata di tipo NSRange. Nella mia versione non posso farlo perché la linea sourceString.rangeOfString(HTMLTags, options: NSStringCompareOptions.RegularExpressionSearch) all'interno del ciclo while restituisce il tipo Range<String.Index> e mi darebbe l'errore Impossibile convertire il tipo dell'espressione '()' per digitare 'NSRange'.

Così ho dichiarato la variabile come questa var range = Range(start: 0, end: 0) ma ora ho un paio di nuovi errori.

Impossibile convertire il tipo di espressione '()' per tipo di errore 'Gamma' alla linea

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

E 'Int' non è identico a 'String.Index' alla linea

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

Ho cercato una soluzione a questo e mi sono imbattuto in questo post. Quindi ho modificato la dichiarazione delle variabili range a questo.

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

Ma ora ricevo questo nuovo errore! Argomento aggiuntivo 'end' in chiamata

Non riesco a trovare un modo per risolvere questo problema. Qualcuno può aiutare, per favore?

Grazie.

risposta

8

Il String metodo di Swift rangeOfString() restituisce un optional Range? che non ha una proprietà location, ma può essere controllato con legame condizionale (if let).

E se si sostituisce il metodo di NSStringstringByReplacingCharactersInRange() con il metodo replaceRange() Swift String (o in questo caso semplicemente removeRange()) allora si può lavorare esclusivamente con Range<Swift.Index> senza convertirlo in 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; 
} 
+0

Fantastico! Enorme grazie come sempre. Ho bisogno di familiarizzare con questo legame condizionale di più. – Isuru

+0

@Isuru: sei il benvenuto! –

+0

Oltre a questa soluzione alternativa, esiste un modo per creare un 'String.Index' da un' Int'? – Rivera

4

Per persone come me che vogliono davvero ottenere 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)) 
} 

Si ha bisogno di fare riferimento alla stringa dove sarai utilizzando la gamma.

+2

In Swift 2, questo è 'return Range (start: string.startIndex.advancedBy (nsRange.location), end: string.startIndex.advancedBy (nsRange.location + nsRange.length))' – jrc

+0

Non è così, noi ' riguardare Range non NSRange –

+0

Questo non funziona con Swift 2, purtroppo. – owlswipe

0

svizzero-esercito pala di vapore per String subscripting, NSRange, Range<Int|String.Index> conversioni

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) 
    } 
} 

Gist here

2

In Swift 2, dato string: String e nsRange: NSRange, questo è

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

Convert NSRange a Range<String.Index> divertimento rapido ction

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