How to implement undo/redo in UIWebView
Asked Answered
U

1

12

I am developing an app which has rich text editor feature. On top of ZSSRichTextEditor I have written my editor code. Here my editor is UIWebView which will be injected by javascript code to support/edit the rich text content.

ZSSRichTextEditor has undo/redo feature but it does not comply with my requirement. So i started to implement undo/redo feature by own.

After I went through UndoManager I came to know that implementing undo/redo will not be a that much headache as Apple helps lot for us. If we register it in proper place then UndoManager will take care of all other thing. But here I am struggling how/where to register UndoManger for editable UIWebView.

There are so many examples to implement undo/redo in UITextView but I don’t find anything for editable UIWebView

Can you some one please guide me on this?

Uriia answered 28/5, 2015 at 6:40 Comment(6)
Just check out this.. Hope so it will work for you [UIWebView with contentEditable][1] [1]: #8474886Potty
This will help you #8474886Potty
By shaking you phone you will get undo/redo option.Fetching
@Fetching thanks for your comment ! the default undo/redo is not working properly it deletes entire text from the editor but for me undo has to work for each character changeUriia
@mohsin sure, I am still waiting for solution :(Uriia
@Uriia — did you ever figure this out? I imagine the iOS JSContext would make it trivial to inject some custom javascript to accomplish what you need.Pietism
P
0

First, create two properties for the history like so:

@property (nonatomic, strong) NSMutableArray *history;
@property (nonatomic) NSInteger currentIndex;

Then what I would do is use subclass ZSSRichTextEditor so that you get delegate calls when a key is pressed or action is done. Then on every delegate call, you can use:

- (void)delegateMethod {
    //get the current html
    NSString *html = [self.editor getHTML];
    //we've added to the history
    self.currentIndex++;
    //add the html to the history
    [self.history insertObject:html atIndex:currentIndex];
    //remove any of the redos because we've created a new branch from our history
    self.history = [NSMutableArray arrayWithArray:[self.history subarrayWithRange:NSMakeRange(0, self.currentIndex + 1)]];
}

- (void)redo {
   //can't redo if there are no newer operations
   if (self.currentIndex >= self.history.count)
       return;
   //move forward one
   self.currentIndex++;
   [self.editor setHTML:[self.history objectAtIndex:self.currentIndex]];
}

- (void)undo {
   //can't undo if at the beginning of history
   if (self.currentIndex <= 0)
       return;
   //go back one
   self.currentIndex--;
   [self.editor setHTML:[self.history objectAtIndex:self.currentIndex]];
}

I would also use some sort of FIFO (First in First out) method to keep the size of the history smaller than 20 or 30 so that you don't have these crazy long strings in memory. But that's up to you depending on how long the content is in the editor. Hope this all makes sense.

Phototonus answered 17/8, 2015 at 17:37 Comment(2)
Thanks for your answer! this will definitely work but I believe there should be some other better way to do this. If you look at the apps like Evernote, OneNote they handled it very well. I will wait for some more days to get appropriate solution otherwise i will go with this approach :-)Uriia
Thanks! I really do think this is how anyone would implement a redo/undo because you need to save state on some sort of stack. I'm not sure how else you would. And the actual delegate method relies, of course, on the library you're usingPhototonus

© 2022 - 2024 — McMap. All rights reserved.