开发者

Undo typing in UITextView [duplicate]

This question already has answers here: Undo/redo with a UITextView (iOS/iPHone) (3 answers) Closed 3 years ago.

I'm using iPhone SDK 3.0.

Say, I enabled 'shake to undo' by setting application.applicationSupportsShakeToEdit to YES in my app delegate. I created an UITextView in RootViewController and had it become first responder upon app launch.

I use - (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text to make changes to the text view according to what the user types. The problem is that it messed up the default undoing action. Shaking the device no longer display 'Undo Typing'.

I tried t开发者_JAVA技巧o create an undo manager myself but have yet to success. Nothing shows up when I shake my device, even though I had the undo manager registered some actionprepareWithInvocationTarget.

Anyone has an idea?

EDIT: I have checked WriteRoom for iPhone's behavior and also TextExpander Touch SDK example code, both of which display the Undo option upon shaking until an auto-completion is made. That is, when a change is commited to the textView via setText:, I guess. So, changing the textView's content indeed has some effects on the undo mechanism.

EDIT 2: The question is that: How could I incorporate the undo feature in this case?


How to incorporate your own undo? Here is the simplest approach possible.

NOTE: this does not respond to shake gesture in simulator.

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 -


The default value for applicationSupportsShakeToEdit is YES so there really shouldn't be any need to turn that on.

I'm not sure exactly what your question/problem is without code, but it's possible that by returning NO on UITextViewDelegate textView:shouldChangeTextInRange you could be short-circuiting the UndoManager magic happening. You might need to review that logic inside that delegate method to make sure that is not happening, or perhaps use a different delegate message like textViewDidChange: instead.


I found the implementation, at least in 3.1 to be buggy and opted to not use undo at all in my app. The bug involved the undo mechanism adding extra undos under certain circumstances, so making the message displayed to the user not make any sense.


Have you looked at the source code here: http://github.com/dcgrigsby/TallyTrucks/tree/master It has a basic (working) implementation of the NSUndoManager. Possibly it could help.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜