- macOS 10.15+
- Xcode 11.0+
This sample code project uses the Compression framework to encode (compress) and decode (decompress) files when you drag them to the app window. The app decompresses files that have extensions matching one of four supported compression algorithms:
.lzfse. The app compresses all files, regardless of their extension. The app writes the encoded or decoded result to the temporary directory returned by the
The code in this sample is useful in applications that store or transmit files, such as PDF or text, where saving or sending smaller files can improve your app’s performance and reduce storage overhead.
This sample walks you through the steps to implement stream compression, where the app reads chucks of data from a source buffer repeatedly to compress or decompress data, appending to a destination buffer.
Accept dropped files.
Select a compression algorithm.
Distinguish whether the dropped file is compressed or uncompressed.
Define the source and destination file handles.
Create a destination buffer.
Create the output filter.
Compress or decompress the dragged file.
Handle any errors that occurred during compression.
Close the source and destination files.
By moving the encoding or decoding to a background thread, you’re able to keep your app interactive and update the user with progress of the operation (for example, with an
NSProgress). Stream compression also enables tasks such as:
Decoding a compressed stream into a buffer, with the ability to grow that buffer and resume decoding if the expanded stream is too large to fit, without repeating any work.
Encoding a stream as pieces of it become available, without ever needing to create a buffer large enough to hold all the uncompressed data at one time.
Accept Dropped Files
After the user drops a conforming file onto the app, the view calls the
perform method. To ensure each item is a URL instance, your app iterates over the dragged items inside
Select a Compression Algorithm
If speed and compression ratio are important for your application of the Compression framework, use
Distinguish Between Compressed and Uncompressed Files
Use the path extension to infer whether a file is already compressed, or if the file needs to be compressed. To simplify this process, create a failable initializer in an extension to the Compression framework’s
Use this new initializer to define the
Define the Source and Destination File Handles
The sample uses
NSFile instances to read from the source file and write to the destination file. Use optional binding to define the required file handles:
If the optional binding succeeded, the destination file handle points to the source filename by appending the respective compression algorithm extension, or removing the extension in the case of decompression.
For example, the compressed source file
My would have a decompressed destination of
My; and the uncompressed source file,
My, would have a compressed destination of
Pass the source and destination file handles, with the operation and algorithm values to the helper function
Create a Destination Buffer
streaming method iterates over the source data, encoding or decoding data in blocks based on the length defined by
buffer. The method writes the result into the destination buffer, and writes the destination buffer data to the destination file handle. The following declares the buffer size and allocates the destination buffer:
Create the Output Filter
You create an
Output instance, that specifies the operation and the compression algorithm, by using the parameters passed to
streaming For more information about other compression algorithms, see
compression. The final initializer parameter is a closure the instance calls as it writes each encoded or decoded block of data to the destination file handler.
Compress or Decompress the Dragged File
Iterate over the source data and call the
read method to copy
buffer chunks to subdata. The
write(_:) method compresses each chunk and uses the closure specified in the OutputFilter initializer to write the result to compressedData.
Handle any Errors That Occurred During Compression
The output filter’s
write(_:) methods can both throw errors. Write code to catch and handle any errors that the output filter may have thrown during the compression stage.
Close the Source and Destination Files
After you’re finished with the source and destination file handles, close them with the