最近公司涉及到作家助手的功能,能撤销输入的文字,并能反撤销被撤销掉的文字。
该功能类似ios系统的摇一摇撤销输入。
当时也特迷茫,不知道从何下手,后来搜索了大量的资料,终于完成了这个功能,现在就将该功能的实现写出来,共勉。
这个功能涉及到ios原生类:NSUndomanager。这个类挺强大。废话不多说,直接上代码。
#import "ViewController.h"
@interface ViewController ()<UITextViewDelegate>{
UITextView *_textView;
NSUndoManager *_undomanager;
NSInteger _length;
UIButton *undobutton;
UIButton *redobutton;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
UIBarButtonItem *undoItem = [[UIBarButtonItemalloc]initWithBarButtonSystemItem:UIBarButtonSystemItemUndotarget:selfaction:@selector(undoitem)];
UIBarButtonItem *redoItem = [[UIBarButtonItemalloc]initWithBarButtonSystemItem:UIBarButtonSystemItemRedotarget:selfaction:@selector(redoitem)];
self.navigationItem.leftBarButtonItem = undoItem;
self.navigationItem.rightBarButtonItem = redoItem;
[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(keyBoardShow:)name:UIKeyboardWillShowNotificationobject:nil];
[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(keyBoardHidden:)name:UIKeyboardWillHideNotificationobject:nil];
_length =0;
//初始化NSUndoManager
_undomanager = [[NSUndoManageralloc] init];
_textView = [[UITextViewalloc]initWithFrame:CGRectMake(0,200, self.view.frame.size.width,400)];
_textView.backgroundColor = [UIColoryellowColor];
_textView.delegate =self;
_textView.font = [UIFontsystemFontOfSize:15];
_textView.layer.cornerRadius =5;
_textView.layer.masksToBounds =YES;
_textView.textColor = [UIColorblackColor];
_textView.text =@" ";//要设置初始文本,不然段落体现不出来。
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStylealloc] init];
paragraphStyle.lineSpacing =5; //行间距
paragraphStyle.firstLineHeadIndent =30; /**首行缩进宽度*/
paragraphStyle.alignment =NSTextAlignmentLeft;
NSDictionary *attributes =@{
NSFontAttributeName:[UIFontsystemFontOfSize:13],
NSParagraphStyleAttributeName:paragraphStyle
};
_textView.attributedText = [[NSAttributedStringalloc] initWithString:_textView.textattributes:attributes];
//监听textview文本改动的通知
[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(changeTextViewText)name:UITextViewTextDidChangeNotificationobject:nil];
[self.viewaddSubview:_textView];
}
-(void)redoitem{
//反撤销
[_undomanagerredo];
}
-(void)undoitem{
//撤销
[_undomanagerundo];
}
-(void)keyBoardShow:(NSNotification *)noti{
NSDictionary *dic = noti.userInfo;
NSValue *aValue = [dicobjectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [aValueCGRectValue];
int height = keyboardRect.size.height;
[_textViewsetContentInset:UIEdgeInsetsMake(0,0, height, 0)];
}
-(void)keyBoardHidden:(NSNotification *)noti{
[_textViewsetContentInset:UIEdgeInsetsMake(0,0, 0,0)];
}
- (void)setMyObjectTitle:(NSString *)newTitle{
//判断当前NSUndoManager的状态,是处于撤销或者反撤销的状态
if (_undomanager.isUndoing) {
NSInteger length = newTitle.length;
if (_textView.text.length>0) {
//获取
_textView.text = [_textView.textsubstringWithRange:NSMakeRange(0,_textView.text.length - length)];
[_undomanagerregisterUndoWithTarget:self
selector:@selector(setMyObjectTitle:)
object:newTitle];
}
}elseif (_undomanager.isRedoing){
_textView.text = [_textView.textstringByAppendingString:newTitle];
[_undomanagerregisterUndoWithTarget:self
selector:@selector(setMyObjectTitle:)
object:newTitle];
}else{
NSString *currentText =_textView.text;
if (newTitle != currentText) {
_textView.text = currentText;
[_undomanagerregisterUndoWithTarget:self
selector:@selector(setMyObjectTitle:)
object:newTitle];
}else{
_textView.text = newTitle;
}
}
}
-(void)changeTextViewText{
if (_textView.text.length>0) {
undobutton.enabled =YES;
}else{
undobutton.enabled =NO;
redobutton.enabled =NO;
}
NSString *text ;
if (_length !=0) {
NSInteger textLength =_textView.text.length;
if (textLength >_length) {
NSInteger newLength = textLength -_length;
text = [NSStringstringWithFormat:@"%@",[_textView.textsubstringWithRange:NSMakeRange(_length, newLength)]];
}else{
text = _textView.text;
}
}else{
text = _textView.text;
}
_length =_textView.text.length;
[selfsetMyObjectTitle:text];
}