2016-01-10 26 views
7

私はSwiftにiOS 9アプリケーションを書いています。 UITextViewをホストするView Controllerがあり、カスタムNSTextStorageオブジェクトを割り当てています。 NSTextStorageは現在のところ基本的なものです。すべてが正常に動作するとテキストがUITextViewに現れたが、私はそれを編集するには、テキストをタップすると、以下の例外を除いて、アプリケーションのクラッシュ: iOS:カスタムNSTextStorageクラッシュを伴うUITextView

2016-01-10 11:24:32.931 PagesWriter[23750:6939530] requesting caretRectForPosition: with a position beyond the NSTextStorage (529) 
2016-01-10 11:24:33.040 PagesWriter[23750:6939530] requesting caretRectForPosition: with a position beyond the NSTextStorage (529) 
2016-01-10 11:24:33.168 PagesWriter[23750:6939530] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSCFString _getBlockStart:end:contentsEnd:forRange:stopAtLineSeparators:]: Range {529, 0} out of bounds; string length 245' 
*** First throw call stack: 
(0x181ea5900 0x181513f80 0x181ea5848 0x18278a02c 0x1827e963c 0x186cc6124 0x186b1c818 0x186cc5fbc 0x186d59e68 0x186bdeb60 0x186bde454 0x186fac1f8 0x187501f64 0x186bc2e84 0x186bc4f40 0x186fa65ac 0x186faea5c 0x186bc5c18 0x186bbf1f8 0x186bbed2c 0x186c2047c 0x186c20828 0x186d5811c 0x186d57f94 0x186d57448 0x187118dbc 0x186d3c5b8 0x186bca9b0 0x18711a3bc 0x186b89b58 0x186b868dc 0x186bc8820 0x186bc7e1c 0x186b984cc 0x186b96794 0x181e5cefc 0x181e5c990 0x181e5a690 0x181d89680 0x183298088 0x186c00d90 0x1000615ec 0x18192a8b8) 
libc++abi.dylib: terminating with uncaught exception of type NSException 

私はUITextViewから私のカスタムNSTextStorageオブジェクトを削除した場合

、それ働く

私のView Controllerは、ストーリーボードのモーダルセグを使用してロードされます。私は、テキストの内容をロードし、viewDidLoadメソッドにUITextViewとNSTextStorageオブジェクトを設定します。

class TextEditorViewController: UIViewController { 
    @IBOutlet weak var textView: UITextView! 

    // Set by parent view controller during transition 
    var URL: NSURL? 

    var textStorage: NSTextStorage? 

    override func viewDidLoad() { 
    super.viewDidLoad() 

    textStorage = CustomTextStorage() 
    textView.textStorage.removeLayoutManager(textView.layoutManager) 
    textStorage!.addLayoutManager(textView.layoutManager) 
    dispatch_async(UtilityQueue) { 
     do { 
     let text = try NSString(contentsOfURL: self.URL!, encoding: NSUTF8StringEncoding) 
     dispatch_async(MainQueue) { 
      self.textStorage!.replaceCharactersInRange(NSRange(location: 0, length: 0), withString: text as String) 
     } 
     } catch { /* handle error */ } 
    } 
    } 
} 

UtilityQueueMainQueueは、対応するディスパッチキューへの参照を保持するヘルパーの内容です。

マイカスタムNSTextStorageクラスは次のようになります。

class CustomTextStorage: NSTextStorage { 
    let backingStore = NSMutableAttributedString() 

    override var string: String { 
    return backingStore.string 
    } 

    override func attributedAtIndex(location: Int, effectiveRange range: NSRangePointer) -> [String: AnyObject] { 
    return backingStore.attributesAtIndex(location, effectiveRange: range) 
    } 

    override func replaceCharactersInRange(range: NSRange, withString str: String) { 
    backingStore.replaceCharactersInRange(range, withString: str) 
    edited(.EditedCharacters, range: range, changeInLength: str.characters.count - range.length) 
    } 

    override func setAttributes(attires: [String: AnyObject]?, range: NSRange) { 
    backingStore.setAttributes(attires, range: range) 
    edited(.EditedAttributes, range: range, changeInLength: 0) 
    } 

    override func processEditing() { 
    /* Placeholder; will be adding code here in the future. */ 
    super.processEditing() 
    } 
} 

任意のアイデア?ご協力いただきありがとうございます。

+0

。私はそれがSwiftと何か関係があると思っています。根本的な原因を見つけたことはありますか? –

+1

私は、swiftで書かれたNSTextStorageサブクラスがこの問題を表示することを確認しました。 Objective-Cの同じ実装は完全に機能します。私はhttps://bugreport.apple.com/にアップル社のレーダーを提出しました。 –

+0

ありがとう@ChristianNiles。私はそれに解決策を見つけませんでした。私はUITextViewの作成と初期化を行い、ストーリーボードのシーンから取り出しました。 –

答えて

-1

お客様のストレージを他の方法で所有する必要があります。あなたが試すことができます

+0

ようこそstackoverflowに!下のコメントボックスを使用してください。十分な評判があれば、投稿にコメントすることができます。 :) –

0

私はそれがまだ関連性があるかどうかわからないが、ほぼ正しいです。

beginEditing()endEditing()にそれぞれ電話する必要があります。

キャスト文字列をNSStringにコールバック編集のための長さで計算します(そうでない場合、絵文字など一部の場合は正常に動作しません)。

また、パフォーマンス上の問題により、NSTextStorageをバッキングストアとして使用してください。

あなたはこのような何かを得るでしょう:私は、Macのアプリで非常に類似したエラーを見ている

final class ExampleStorage : NSTextStorage { 

    private let container = NSTextStorage() 

    override var string: String { 
     return container.string 
    } 

    override func attributes(at location: Int, effectiveRange range: NSRangePointer?) -> [NSAttributedStringKey : Any] { 
     return container.attributes(at: location, effectiveRange: range) 
    } 

    override func replaceCharacters(in range: NSRange, with str: String) { 
     beginEditing() 
     container.replaceCharacters(in: range, with: str) 
     edited([.editedAttributes, .editedCharacters], range: range, changeInLength: (str as NSString).length - range.length) 
     endEditing() 
    } 

    override func setAttributes(_ attrs: [NSAttributedStringKey : Any]?, range: NSRange) { 
     beginEditing() 
     container.setAttributes(attrs, range: range) 
     edited([.editedAttributes], range: range, changeInLength: 0) 
     endEditing() 
    } 
} 
+0

NSTextStorageをバッキングストアとして使用する理由を明確にすることはできますか?パフォーマンスの問題は何ですか? –

+0

私は特定の調査をしませんでした。 1〜2年前にiOSでリッチエディタを実装した経験の後、何らかの神様の気持ちが感じられます。また、NSMutableAttributedStringを使っていくつかの[メモリ関連の問題](https://stackoverflow.com/a/37953430/588673) –

関連する問題