« xDev Magazine 22.5 Is… | Home | Deprecation of TLS 1.… »

Managing File Access in Xojo with NSFileCoordinator

In the realm of cross-platform development, handling file access consistently across different operating systems can be a challenging task. For Xojo developers working on macOS or iOS, NSFileCoordinatorMBS and NSFilePresenterMBS from the Monkeybread Software’s Xojo plugins offer a powerful way to manage file access while avoiding conflicts with iCloud. In this blog post, we’ll delve into a practical example of using these classes in a Xojo project.

Introduction to NSFileCoordinatorMBS and NSFilePresenterMBS

Before we dive into the code, let’s briefly understand what NSFileCoordinatorMBS and NSFilePresenterMBS do:

  • NSFileCoordinatorMBS: This class helps in coordinating access to files across different processes. It ensures that multiple processes can read from or write to a file without interfering with each other, thus avoiding file access conflicts.
  • NSFilePresenterMBS: This class works in tandem with NSFileCoordinatorMBS and represents a file or directory that presents its state to the file coordinator. It allows your app to be notified of changes to the file or directory it is coordinating. We won’t really use this class today.

Example Scenario

Let’s walk through a simple Xojo application example where a user selects a file, and the application reads its contents. We will use NSFileCoordinatorMBS and NSFilePresenterMBS to manage file access on macOS or iOS while skipping these steps on Windows and Linux.

Sample Code Explained

Here’s a breakdown of the code provided:

Class MainWindow Inherits DesktopWindow

    Control OpenButton Inherits DesktopButton

        ControlInstance OpenButton Inherits DesktopButton

        EventHandler Sub Pressed()

            var ofd as new OpenFileDialog

            

            var f as FolderItem = ofd.ShowModal(Self)

            

            if f = nil then return

            

            #if TargetMacOS or TargetIOS then

                fp = new NSFilePresenterMBS

                fc = new NSFileCoordinatorMBS(fp)

                

                AddHandler fc.coordinateReadingItemAtURL, AddressOf coordinateReadingItemAtURL

                

                // don't ask other apps to save change

                var error as NSErrorMBS

                var flags as integer = NSFileCoordinatorMBS.NSFileCoordinatorReadingWithoutChanges

                fc.coordinateReadingItemAtURL(f, flags, error)

                

                if error <> nil then

                    MessageBox error.localizedDescription

                end if

            #else

                // Windows and Linux skip this

                ReadTheFile file

            #endif

        End EventHandler

    End Control

    Sub ReadTheFile(file as FolderItem)

        var b as BinaryStream = BinaryStream.Open(file)

        

        var Data as string = b.Read(b.Length)

        

        MessageBox "Read file with "+data.Bytes.ToString+" bytes"

    End Sub

    Sub coordinateReadingItemAtURL(N as NSFileCoordinatorMBS, url as string, file as folderitem, tag as Variant)

        // we got access

        ReadTheFile file

    End Sub

    Property fc As NSFileCoordinatorMBS

    Property fp As NSFilePresenterMBS

End Class

1. Setting Up the Open File Dialog

The OpenButton control’s Pressed event handler is triggered when the user clicks the button:

var ofd as new OpenFileDialog

var f as FolderItem = ofd.ShowModal(Self)

Here, we present the user with an OpenFileDialog to select a file. If the user cancels the dialog, f will be nil, and the method exits.

2. Conditional Code for macOS/iOS

For macOS and iOS, we initialize NSFilePresenterMBS and NSFileCoordinatorMBS. We connect the coordinateReadingItemAtURL event with out local method and ask the system to coordinate reading and notify us with an error if this fails or later call the callback method.

#if TargetMacOS or TargetIOS then

    fp = new NSFilePresenterMBS

    fc = new NSFileCoordinatorMBS(fp)

    

    AddHandler fc.coordinateReadingItemAtURL, AddressOf coordinateReadingItemAtURL

    

    var error as NSErrorMBS

    var flags as integer = NSFileCoordinatorMBS.NSFileCoordinatorReadingWithoutChanges

    fc.coordinateReadingItemAtURL(f, flags, error)

    

    if error <> nil then

        MessageBox error.localizedDescription

    end if

#else

    ReadTheFile file

#endif

You could subclass NSFileCoordinatorMBS instead of using addHandler if you prefer that of course. But the advance of using delegate, is that you don’t need to subclass each time you call it and just connect the event in code to som method.

While the sample code uses properties to store fp and fc, this is not really necessary. The coordinateReadingItemAtURL method retains the fc object reference and passes it to the delegate method. Once done, this reference gets released automatically.

3. Reading the File

If there are no errors during coordination, the coordinateReadingItemAtURL method is called, which then proceeds to read the file:

Sub ReadTheFile(file as FolderItem)

    var b as BinaryStream = BinaryStream.Open(file)

    var Data as string = b.Read(b.Length)

    MessageBox "Read file with "+data.Bytes.ToString+" bytes"

End Sub

This method reads the contents of the file and displays a message box with the number of bytes read. We call this directly for Windows and Linux since we don’t coordinate there.

4. Handling File Access Coordination Completion

The coordinateReadingItemAtURL method confirms that access to the file has been coordinated and then calls ReadTheFile to perform the actual file reading.

Conclusion

Using NSFileCoordinatorMBS and NSFilePresenterMBS ensures that your Xojo application handles file access gracefully, particularly on macOS and iOS where multiple processes might interact with the same files. This approach helps in avoiding file access conflicts and ensures a smooth user experience. On Windows and Linux, the code simply reads the file without the added complexity of file coordination.

By incorporating these classes, Xojo developers can create robust cross-platform applications that handle file operations consistently and effectively.

The biggest plugin in space...
05 09 24 - 06:24