【问题标题】:Undo typing in UITextView [duplicate]撤消在 UITextView 中输入 [重复]
【发布时间】:2010-12-31 19:18:03
【问题描述】:

我正在使用 iPhone SDK 3.0。

比如说,我通过在我的应用程序委托中将application.applicationSupportsShakeToEdit 设置为YES 启用了“摇动撤消”。我在 RootViewController 中创建了一个 UITextView,并让它在应用启动时成为第一响应者。

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

我尝试自己创建一个撤消管理器,但尚未成功。即使我让撤消管理器注册了一些操作prepareWithInvocationTarget,当我摇动设备时也没有任何显示。

有人有想法吗?

编辑:我检查了 WriteRoom 以了解 iPhone 的行为以及 TextExpander Touch SDK 示例代码,它们都在摇动时显示撤消选项,直到自动完成。也就是说,当通过 setText: 向 textView 提交更改时,我猜。所以,改变 textView 的内容确实对 undo 机制有一些影响。

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

【问题讨论】:

    标签: iphone uitextview nsundomanager


    【解决方案1】:

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

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

    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 -
    

    【讨论】:

    • 虽然这不是我真正想要的(喜欢使用内置的 NSUndoManager),但它确实是解决问题的一种方法。所以给你,100次。
    • 你能定义你的常量,这样我就可以测试了。感谢您的帮助!
    【解决方案2】:

    applicationSupportsShakeToEdit 的默认值是YES,所以真的不需要打开它。

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

    【讨论】:

    • 我也认为返回 NO 对撤消机制做了一些事情,但不知道如何解决这个问题。不幸的是 textView:shouldChangeTextInRange: 正是我需要使用的,因为我必须对输入本身进行更改。
    • 返回 NO 会阻止对 textview 的任何编辑,并且摇动撤消会显示一个标有“无撤消操作”的提示。
    【解决方案3】:

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

    【讨论】:

    • 您能否详细说明这些“某些情况”?我对在我的应用中添加撤消功能非常感兴趣。
    • 我查到了这个。我遇到的问题是 self.editingView.text = someTextString;将没有 actionName 的撤消事件添加到堆栈中。当用户去撤消时,他们会看到一个撤消弹出窗口,在任何真正的弹出窗口之前对他们来说没有任何意义。
    • 我自己在一个应用程序中成功使用了 [apptree.net/gcundomanager.htm] 来替换 UITextView 中的 NSUndoManager。它当然可以在模拟器上运行,尽管我还没有在设备上尝试过。我的目标是 iOS 4.0+。
    【解决方案4】:

    你看过这里的源代码吗:http://github.com/dcgrigsby/TallyTrucks/tree/master 它具有 NSUndoManager 的基本(工作)实现。可能会有帮助。

    【讨论】:

    • 是的,我看过了。不过没有帮助。
    猜你喜欢
    • 2011-05-03
    • 2011-11-19
    • 1970-01-01
    • 2018-11-04
    • 1970-01-01
    • 2016-02-12
    • 2021-02-13
    • 1970-01-01
    • 2017-05-11
    相关资源
    最近更新 更多