5

Desidero modificare alcuni o tutti il ​​testo attribuito di un UITextView avanzato (iOS 6) e consentire all'utente di annullare la modifica.Annulla l'operazione con NSUndoManager in UITextView avanzato (iOS 6)

Dopo aver letto NSUndoManager documentation, ho provato il primo modo:

“Simple undo” based on a simple selector with a single object argument. 

mi aspettavo un'operazione di annullamento per essere il più semplice:
Dichiarare questo metodo:

- (void)setAttributedStringToTextView:(NSAttributedString *)newAttributedString { 

    NSAttributedString *currentAttributedString = self.textView.attributedText; 

    if (! [currentAttributedString isEqualToAttributedString:newAttributedString]) { 
     [self.textView.undoManager registerUndoWithTarget:self 
            selector:@selector(setAttributedStringToTextView:) 
             object:currentAttributedString]; 
     [self.textView.undoManager setActionName:@"Attributed string change"]; 
     [self.textView setAttributedText:newAttributedString]; 
    } 
} 

Modificare il testo nella mia UITextView chiamando:

[self setAttributedStringToTextView:mutableAttributedString]; 

Ma dopo averlo fatto, NSUndoManager dice che non può annullare.

NSLog(@"Can undo: %d", [self.textView.undoManager canUndo]); 
// Prints: "Can undo: 0" 




così ho provato il secondo modo:

“Invocation-based undo” which uses an NSInvocation object. 

dichiararlo:

- (void)setMyTextViewAttributedString:(NSAttributedString *)newAttributedString { 

     NSAttributedString *currentAttributedString = [self.textView attributedText]; 
    if (! [currentAttributedString isEqualToAttributedString:newAttributedString]) { 
     [[self.textView.undoManager prepareWithInvocationTarget:self] 
     setMyTextViewAttributedString:currentAttributedString]; 
     [self.textView.undoManager setActionName:@"Attributed string change"]; 
     [self.textView setAttributedText:newAttributedString]; 
    } 
} 

e modificare il testo con:

[self setMyTextViewAttributedString:mutableAttributedString]; 

Successivamente, NSUndoManager dice anche che non può annullare.

Perché?

Si noti che l'utente sta modificando UITextView quando si attiva il codice che cambierà il testo attribuito.




Una soluzione sarebbe quella di sostituire il testo direttamente tramite metodo di protocollo UITextInput. Il seguente metodo è abbastanza conveniente, ma non ho trovato un equivalente per NSAttributedString. Mi è mancato?

- (void)replaceRange:(UITextRange *)range withText:(NSString *)text 

Un trucco suggerito qui è di simulare un'operazione di incolla. Se possibile, preferirei evitare questo (ancora nessuna ragione, mi sento troppo sporco per non tornare a mordermi più tardi).

+0

Si è verificato che '' self.textView', self.textView.attributedText', e 'self.textView.undoManager' sono tutte per non 'nil'? –

+0

Sì. self.textView.attributedText = newValue viene effettivamente aggiornato nell'interfaccia utente. E textView.undoManager è membro della classe WebThreadSafeUndoManager ed è la stessa istanza per tutto il ciclo di vita del mio viewController. – Guillaume

+1

Ho notato lo stesso problema. Posso annullare alcune operazioni ma non una sostituzione AttribuitoString. Non è stato trovato alcun rimedio (consultare http://stackoverflow.com/questions/12501541/uitextview-undo-manager-do-not-work-with-replacement-attributed-string-ios-6) – Denis

risposta

1

Sono ancora in stato di shock, funziona. Ho postato la stessa risposta qui UITextView undo manager do not work with replacement attributed string (iOS 6).

- (void)applyAttributesToSelection:(NSDictionary*)attributes { 
    UITextView *textView = self.contentCell.textView; 

    NSRange selectedRange = textView.selectedRange; 
    UITextRange *selectedTextRange = textView.selectedTextRange; 
    NSAttributedString *selectedText = [textView.textStorage attributedSubstringFromRange:selectedRange]; 

    [textView.undoManager beginUndoGrouping]; 
    [textView replaceRange:selectedTextRange withText:selectedText.string]; 
    [textView.textStorage addAttributes:attributes range:selectedRange]; 
    [textView.undoManager endUndoGrouping]; 

    [textView setTypingAttributes:attributes]; 
}