2016-03-30 7 views
0

文字列のstartIndexと別のインデックスの間の距離を取得しようとしますが、最初のループ反復で次のエラーが発生します。コードは実際にはほとんどの文字列で動作しますが、一部ではクラッシュします。String.anotherIndexは "致命的なエラーを引き起こします:endIndexをインクリメントできません"

fatal error: cannot increment endIndex

let content = NSMutableAttributedString(string: rawContent, attributes: attrs) 

var startIndex = content.string.characters.startIndex 

while true { 
    let searchRange = startIndex..<rawContent.characters.endIndex 
    if let range = rawContent.rangeOfString("\n", range: searchRange) { 
     let index = rawContent.characters.startIndex.distanceTo(range.startIndex) 
     startIndex = range.startIndex.advancedBy(1) 

     rawContent.replaceRange(range, with: "*") 
     content.addAttribute(
      NSForegroundColorAttributeName, 
      value: UIColor.redColor(), 
      range: NSMakeRange(index, 1)) 
    } 
    else { 
     break 
    } 
} 

content.replaceCharactersInRange(NSMakeRange(0, content.length), withString: rawContent) 

contentNSMutableAttributedStringで、アプリの変数は以下の値を持ってクラッシュしたとき:

range.startIndex: 164 
content.string.characters.startIndex: 0 
content.string.characters.endIndex: 437, 
content.string.characters.count: 435 

エラーメッセージは、私がしようとしているときendIndexのを増やすことについて述べている理由を私は理解していませんstartIndexからの距離を計算し、anotherIndexは文字列の長さよりも小さい。

+0

これらの4行のコードからエラーが発生していますか? – Putz1103

+0

デバッガは最後の行で停止します。 – Tapani

+0

質問にすべての行を追加しました。デバッガは、最初のループの反復でlet let index = ...という行で停止します。これまでコードは正常に動作していましたが、一部の文字列ではクラッシュすることはありませんでした。文字列には、改行を含む通常のテキストが含まれています。 – Tapani

答えて

0

あなたのコードは正常に動作しましたが、エラーチェックが必要です。とにかくcontent.string全体を検索しているので、検索範囲の設定が複雑になるのはなぜですか?

このような何かが単純になります:

if let anotherIndex = content.string.rangeOfString("\n") 
{ 
    let index = content.string.startIndex.distanceTo(anotherIndex.startIndex) 
} 
+0

私のコードは実際にはループであるため、必要なチェックが行われているため、範囲を使用しています。しかし、それはループの最初のラウンドでクラッシュします。 – Tapani

+0

コード全体が含まれるように質問を更新しました。 – Tapani

2

エラーの原因は、あなたがRange<String.Index>NSRange APIを混合していることです。最初はCharacterでカウントされ、秒はUTF-16コード単位でカウントされます。あなたが起動した場合:

import Cocoa 

let content = NSMutableAttributedString(string: "♥️♥️\n") 

...その後、あなたのコードは無限ループに入る(これはTapaniの元の質問@を指し、これはまだ彼の変更後の場合であれば、私はチェックしていません。中央の問題が残っています同じだけど)!あなたは順番にループであなたを保つ場所で新しい行を残して、スペースを有する第二の心臓(の一部)を交換終わるように...

NSString(string: "♥️♥️\n").length // 5 
"♥️♥️\n".characters.count   // 3 

:これがあるためです。これらの問題を回避する

一つの方法は、の線に沿って何か行うことです:あなたはコピーして遊び場にこれを貼り付けると、コードを勉強すれば

let content = NSMutableAttributedString(string: "♥️♥️\n") 

let newLinesPattern = try! NSRegularExpression(pattern: "\\n", options: []) 

let length = (content.string as NSString).length 
let fullRange = NSMakeRange(0, length) 

let matches = newLinesPattern.matchesInString(content.string, options: [], range: fullRange) 

for match in matches.reverse() { 
    content.replaceCharactersInRange(match.range, withAttributedString: NSAttributedString(string: " ")) 
} 

content.string // "♥️♥️ " 

を(例えば自分がポップアップするメソッド名にAltキーを押しながらクリックしてくださいAPI)を使用すると、このコードはNSRangeメトリックでのみ動作することがわかります。また、マッチした範囲を逆順にループしているので、異なる長さの部分文字列で置き換えることができますので、はるかに安全です。さらに、NSRegularExpressionを使用すると、より一般的な解決策になります(パターンを保存して他の場所で再利用することもできます)。最後に、NSAttributedStringに置き換えて、に加えてNSRangeを基にして、既存の属性を保持する(置換する範囲から取得する)か、他の属性を追加することができます。

+0

しかし、それはあなたがインデックスから見ることができるようにクラッシュの原因ではありません。私の文字列に0〜255の範囲にない文字はありません。 – Tapani

+1

あなたの 'characters.endIndex'は437で' characters.count'は435なので、それは事実ではありません。だから、1人か2人の "悪人"のキャラクターが夢中になったのでしょうか? – milos

+0

また、Swift Stringのインデックスを使用してNSAttributed文字列内の範囲に範囲を置き換えたり、範囲に属性を追加する方法はありますか? – Tapani

関連する問題