2011-06-21 53 views
9

我希望能夠置換的UITextView的編程一些文字,所以我寫了這個方法的UITextView的類別:如何使用NSUndoManager支持替換UITextView中的文本?

- (void) replaceCharactersInRange:(NSRange)range withString:(NSString *)newText{ 

    self.scrollEnabled = NO; 

    NSMutableString *textStorage = [self.text mutableCopy]; 
    [textStorage replaceCharactersInRange:range withString:newText]; 

    //replace text but undo manager is not working well 
    [[self.undoManager prepareWithInvocationTarget:self] replaceCharactersInRange:NSMakeRange(range.location, newText.length) 
                     withString:[textStorage substringWithRange:range]]; 
    NSLog(@"before replacing: canUndo:%d", [self.undoManager canUndo]); //prints YES 
    self.text = textStorage; 
    NSLog(@"after replacing: canUndo:%d", [self.undoManager canUndo]); //prints NO 
    if (![self.undoManager isUndoing])[self.undoManager setActionName:@"replace characters"]; 
    [textStorage release]; 

    //new range: 
    range.location = range.location + newText.length; 
    range.length = 0; 
    self.selectedRange = range; 

    self.scrollEnabled = YES; 

} 

它的工作原理,但NSUndoManager停止工作(這似乎是復位)只是做self.text=textStorage後我發現了一個私有API:-insertText:(NSString *)可以完成這項工作,但是誰知道如果我使用它,Apple是否會批准我的應用程序。有沒有什麼辦法在UITextView中用NSUndoManager支持取代文本?或者我可能在這裏錯過了一些東西?

回答

5

實際上沒有任何黑客或自定義類別來完成此任務的理由。您可以使用內置的UITextInput協議方法replaceRange:withText:。對於插入文本,你可以簡單地做:

[textView replaceRange:textView.selectedTextRange withText:replacementText]; 

這適用於iOS 5.0。撤銷自動工作,沒有奇怪的滾動問題。

+1

這不是100%正確。 'replaceRange:withText'將完成這項工作,而UITextInput協議確實可以從3.2版本獲得,但UITextView直到5.0版本才採用它。所以這個答案只適用於OS5.0及以上版本 – nacho4d

+0

我根據@ nacho4d的評論更新了我的答案。接得好。 – mightylost

+0

是的,這是iOS 5的方式。 –

1

它不應該是

[[self.undoManager prepareWithInvocationTarget:self] replaceCharactersInRange:NSMakeRange(range.location, newText.length) 
                    withString:[self.text substringWithRange:range]]; 

你或許終於可以卸下可變的字符串,只是做的,

self.text = [self.text stringByReplacingCharactersInRange:range withString:newText]; 
+0

我認爲你是對的,應該是這樣。我試過了,但那並不能解決問題。一旦'self.text = textStorage'完成,NSUndoManager就無法撤銷。 – nacho4d

+0

你什麼時候觸發這種方法?我想重現這一點。如果你能給我一些示例代碼,那就更好了。 –

+0

我有一個inputAccessoryView爲我的UITexView,與一些按鈕。我使用這個時按下按鈕來插入文本中的一些字符 – nacho4d

3

已經絆了這個問題,並得到它灰白的頭髮後,我找到了令人滿意的解這有點俗氣,但它的功能如同魅力。這個想法是使用UITextView提供的工作副本&粘貼支持!我想你可能會感興趣:

- (void)insertText:(NSString *)insert 
{ 
    UIPasteboard *pboard = [UIPasteboard generalPasteboard]; 

    // Clear the current pasteboard 
    NSArray *oldItems = [pboard.items copy]; 
    pboard.items = nil; 

    // Set the new content to copy 
    pboard.string = insert; 

    // Paste 
    [self paste: nil]; 

    // Restore pasteboard 
    pboard.items = oldItems; 
    [oldItems release]; 
} 

編輯:當然,你可以自定義此代碼在文本視圖中的任何位置插入文本。在致電paste之前,請設置selectedRange

+0

這種方法的唯一缺點是操作名稱將是「撤消粘貼」而不是「撤消鍵入」(此消息在晃動設備時出現,因此NSUndoManager警報將顯示) – nacho4d

+0

@ nacho4d沒錯,但至少在iPad上,大多數用戶會使用鍵盤上的不顯示名稱的撤銷/重做按鈕。你是否嘗試用'NSUndoManager'的'setActionName:'給它一個自定義名稱?也許你需要一個撤消組或大約 –

+0

我將如何將「撤消粘貼」更改爲「撤消鍵入」?我可以在[self paste:nil]之後調用setActionName:? – nacho4d

相關問題