2016-01-10 16 views
7

Sto scrivendo un'applicazione iOS 9 in Swift. Ho un controller di visualizzazione che ospita un UITextView e sto assegnando un oggetto NSTextStorage personalizzato ad esso. Il NSTextStorage è semplicemente di base adesso. Tutto funziona correttamente e il testo si presenta nella UITextView, ma quando io batto sul testo per modificarlo, l'applicazione si blocca con la seguente eccezione:iOS: UITextView con arresto anomalo NSTextStorage personalizzato

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 

Se rimuovo il mio oggetto NSTextStorage personalizzato dal UITextView, si lavori.

Il controller di visualizzazione viene caricato utilizzando un passaggio modale nello storyboard. Ho caricare il contenuto del testo e configurare gli oggetti UITextView e NSTextStorage nel metodo viewDidLoad:

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 */ } 
    } 
    } 
} 

UtilityQueue e MainQueue sono contenuti helper che tengono un riferimento alla coda di invio corrispondente.

mia classe personalizzata NSTextStorage si presenta così:

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

Tutte le idee? Grazie in anticipo per la vostra assistenza.

+0

sto vedendo un errore molto simile in un'applicazione per Mac. Ho l'impressione che abbia qualcosa a che fare con Swift. Hai mai trovato la causa principale? –

+1

Ho verificato che le sottoclassi NSTextStorage scritte in swift mostreranno questo problema. Un'implementazione identica in Objective-C funziona perfettamente. Ho archiviato un radar con apple su https://bugreport.apple.com/ e dovresti farlo anche tu. –

+0

Grazie a @ChristianNiles. Non ho trovato una soluzione. Ho appena spostato la creazione e l'inizializzazione di UITextView per il codice e l'ho tolto dalla scena dello storyboard. –

risposta

-1

è necessario possedere l'archiviazione del cliente in altri modi. puoi provare

+0

Benvenuti nello stackoverflow !! Si prega di utilizzare la casella di commento qui sotto e una volta che si ha sufficiente reputazione si sarà in grado di commentare qualsiasi post. :) –

0

Non so se è ancora rilevante, ma hai quasi ragione.

È necessario chiamare rispettivamente beginEditing() e endEditing().

Fusione stringa a NSString nel calcolo della lunghezza per la modifica del callback (in caso contrario, emoji e alcuni altri casi non funzioneranno correttamente).

Inoltre, utilizzare NSTextStorage come backingStore a causa di problemi di prestazioni.

otterrete qualcosa di simile:

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

Puoi chiarire il motivo per cui dovresti usare NSTextStorage come backing store? Qual è il problema delle prestazioni? –

+0

Non ho fatto alcune indagini specifiche. È una specie di sentimento di Dio dopo la mia esperienza nell'implementazione di editor avanzato su iOS uno o due anni fa. Puoi anche trovare alcuni [problemi relativi alla memoria] (https://stackoverflow.com/a/37953430/588673) in giro con NSMutableAttributedString –

Problemi correlati