> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/ios/get-started/samples/undoredotest.md).

# UndoRedoTest

Sample Obj-C code for using Apryse SDK to take snapshots of edits and move between them using the API.

The Apryse SDK has a low-level facility for undo and redo operations. It is a API that applies to any edits made to a particular document (not just annotations). This sample Obj-C code shows how to use Apryse SDK to walk back and forth on a fully general, bit-exact list of document states. Saving changes in a mode that is not 'incremental' will wipe out the undo-redo state list; the API will not be able to access old snapshots anymore. See the [undoing and redoing guide](/core/pdf-editing/undoredo.md) for more information. Learn more about our [iOS SDK](/ios/guides.md).

{% tabs %}
{% tab title="Obj-C" %}
{% code lineNumbers="true" %}

```objc
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

#import <OBJC/PDFNetOBJC.h>
#import <Foundation/Foundation.h>
#include <math.h>

//---------------------------------------------------------------------------------------
// The following sample illustrates how to use the UndoRedo API.
//---------------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    @autoreleasepool
    {
        int ret = 0;
        
        @try
        {
            // The first step in every application using PDFNet is to initialize the 
            // library and set the path to common PDF resources. The library is usually 
            // initialized only once, but calling Initialize() multiple times is also fine.
            [PTPDFNet Initialize: 0];

            // Open the PDF document.
            PTPDFDoc *doc = [[PTPDFDoc alloc] initWithFilepath: @"../../TestFiles/newsletter.pdf"];
            
            PTSDFUndoManager* undo_manager = [doc GetUndoManager];
            
            // Take a snapshot to which we can undo after making changes.
            PTSDFResultSnapshot* snap0 = [undo_manager TakeSnapshot];
            
            PTSDFDocSnapshot* snap0_state = [snap0 CurrentState];
            
            PTElementBuilder* builder = [[PTElementBuilder alloc] init];    // Used to build new Element objects
            PTElementWriter* writer = [[PTElementWriter alloc] init];       // Used to write Elements to the page  
            
            PTPDFRect * rect = [[PTPDFRect alloc] init]; 
            [rect Set: 0 y1: 0 x2: 612 y2: 792];
            
            PTPage* page = [doc PageCreate: rect];  // Start a new page
            
            [writer WriterBeginWithPage: page placement: e_ptoverlay page_coord_sys: YES compress: YES resources: NULL];    // Begin writing to this page

            // ----------------------------------------------------------
            // Add JPEG image to the file
            PTImage* img = [PTImage Create: [doc GetSDFDoc] filename: @"../../TestFiles/peppers.jpg"];
            PTElement* element = [builder CreateImageWithMatrix: img mtx: [[PTMatrix2D alloc] initWithA: 200 b: 0 c: 0 d: 250 h: 50 v: 500]];
            [writer WritePlacedElement: element];
            
            [writer End];    // Finish writing to the page
            [doc PagePushFront: page];
            
            // Take a snapshot after making changes, so that we can redo later (after undoing first).
            PTSDFResultSnapshot* snap1 = [undo_manager TakeSnapshot];
            
            if ([[snap1 PreviousState] Equals: snap0_state])
            {
                NSLog(@"snap1 previous state equals snap0_state; previous state is correct");
            }
            
            PTSDFDocSnapshot* snap1_state = [snap1 CurrentState];
            
            [doc SaveToFile: @"../../TestFiles/Output/addimage.pdf" flags: e_ptincremental];
            
            if ([undo_manager CanUndo])
            {
                PTSDFResultSnapshot* undo_snap = [undo_manager Undo];
                
                [doc SaveToFile: @"../../TestFiles/Output/addimage_undone.pdf" flags: e_ptincremental];
                
                PTSDFDocSnapshot* undo_snap_state = [undo_snap CurrentState];
                
                if ([undo_snap_state Equals: snap0_state])
                {
                    NSLog(@"undo_snap_state equals snap0_state; undo was successful");
                }
                
                if ([undo_manager CanRedo])
                {
                    PTSDFResultSnapshot* redo_snap = [undo_manager Redo];
                    
                    [doc SaveToFile: @"../../TestFiles/Output/addimage_redone.pdf" flags: e_ptincremental];
                    
                    if ([[redo_snap PreviousState] Equals: undo_snap_state])
                    {
                        NSLog(@"redo_snap previous state equals undo_snap_state; previous state is correct");
                    }
                    
                    PTSDFDocSnapshot* redo_snap_state = [redo_snap CurrentState];
                    
                    if ([redo_snap_state Equals: snap1_state])
                    {
                        NSLog(@"Snap1 and redo_snap are equal; redo was successful");
                    }
                }
                else
                {
                    NSLog(@"Problem encountered - cannot redo.");
                    ret = 1;
                }
            }
            else
            {
                NSLog(@"Problem encountered - cannot undo.");
                ret = 1;
            }
        }
        @catch(NSException *e)    
        {
            NSLog(@"%@", e.reason);
            ret = 1;
        }
        [PTPDFNet Terminate: 0];
        return ret;
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/ios/get-started/samples/undoredotest.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
