撤消在UITextView中输入

时间:2010-01-02 15:27:37

标签: iphone uitextview nsundomanager

我正在使用iPhone SDK 3.0。

说,我通过在我的应用代理中将application.applicationSupportsShakeToEdit设置为YES来启用“动摇撤消”功能。我在RootViewController中创建了一个UITextView,并在应用程序启动后成为第一响应者。

我使用- (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text根据用户输入的内容对文本视图进行更改。问题是它搞砸了默认的撤消操作。摇动设备不再显示“撤消键入”。

我试图自己创建一个撤销管理器,但还没有成功。即使我让撤消管理器注册了一些操作prepareWithInvocationTarget,我也无法在摇动设备时显示任何内容。

有人有想法吗?

编辑:我已经检查过WriteRoom for iPhone的行为以及TextExpander Touch SDK示例代码,两者都会在摇动时显示“撤消”选项,直到自动完成为止。也就是说,当通过setText:将更改提交到textView时,我想。因此,更改textView的内容确实会对撤消机制产生一些影响。

编辑2 :问题是:在这种情况下如何合并撤消功能?

5 个答案:

答案 0 :(得分:4)

如何合并您自己的撤消?这是最简单的方法。

注意:这不会响应模拟器中的摇动手势。

<强> UndoTestViewController.h:

@interface UndoTestViewController : UIViewController <UITextViewDelegate, UIAccelerometerDelegate>{
    IBOutlet UITextView *textview;
    NSString *previousText;
    BOOL showingAlertView;
}
@property (nonatomic,retain) NSString *previousText;
@end

<强> UndoTestViewController.m:

@implementation UndoTestViewController
@synthesize previousText;

- (void)viewDidLoad {
    [super viewDidLoad];

    //disable built-in undo
    [UIApplication sharedApplication].applicationSupportsShakeToEdit = NO;

    showingAlertView = NO;

    [UIAccelerometer sharedAccelerometer].delegate = self; 
    [UIAccelerometer sharedAccelerometer].updateInterval = kUpdateInterval;

    //set initial undo text
    self.previousText = textview.text;
}

#pragma mark UITextViewDelegate
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {

    //save text before making change
    self.previousText = textView.text;

    //changing text in some way...
    textView.text = [NSString stringWithFormat:@"prepending text %@",textView.text];
    [textView resignFirstResponder];
    return YES;
}
#pragma mark -

#pragma mark UIAccelerometerDelegate
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { 

    if( showingAlertView ) return;

    if ( acceleration.x > kAccelerationThreshold || 
        acceleration.y > kAccelerationThreshold || 
        acceleration.z > kAccelerationThreshold ) {


        showingAlertView = YES;
        NSLog(@"x: %f y:%f z: %f", acceleration.x, acceleration.y, acceleration.z);


        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Undo Typing", nil];
        alert.delegate = self;
        [alert show];
        [alert release];
    }
}
#pragma mark -

#pragma mark UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if( buttonIndex == 1 ) {
        textview.text = self.previousText;
    }
    showingAlertView = NO;
}
#pragma mark -

答案 1 :(得分:1)

applicationSupportsShakeToEdit的默认值为YES,因此确实不需要打开它。

我不确定你的问题/问题究竟是什么没有代码,但是有可能通过在UITextViewDelegate textView:shouldChangeTextInRange上返回NO你可能会使UndoManager魔法发生短路。您可能需要检查该委托方法中的逻辑,以确保不会发生这种情况,或者可能使用不同的委托消息,例如textViewDidChange:

答案 2 :(得分:0)

我发现实现,至少在3.1中是错误的,并选择在我的应用程序中根本不使用撤消。该错误涉及在某些情况下添加额外撤消的撤消机制,因此向用户显示消息没有任何意义。

答案 3 :(得分:0)

您是否在此处查看了源代码:http://github.com/dcgrigsby/TallyTrucks/tree/master 它具有NSUndoManager的基本(工作)实现。可能它会有所帮助。

答案 4 :(得分:0)

我找到了解决问题的方法 - 概述了here in iPhoneDevDude's answer