📁 LSFileWrapper

Platforms GitHub Swift Package Manager Build iOS Build macOS

NSFileWrapper 的替代品,可以按需加载/保存内容。它专门设计用于处理大型包/捆绑包或具有多个文件条目的目录。它需要的内存占用空间极小,因为它不会尝试将所有内容加载到内存中(与 Apple 的 NSFileWrapper 不同),而是尝试仅在主动使用时才对单个文件进行内存映射。这个库还内置了方便的方法,用于保存/序列化对象,如 NSData、UIImage、NSImage、NSDictionary 等等...

💻 要求

LSFileWrapper 可以在 Mac OS X 10.7+ 和 iOS 8.0 或更高版本上运行。 Xcode 项目包含两个框架目标:

📖 用法

创建新的包装器

要创建新的 LSFileWrapper,目录包装器请使用 -initDirectory,常规文件包装器请使用 -initFile。这些包装器及其所有内容将完全存储在内存中,直到调用任何写入方法。

LSFileWrapper* newDirectoryWrapper = [[LSFileWrapper alloc] initDirectory];
LSFileWrapper* newRegularFileWrapper = [[LSFileWrapper alloc] initFile];

Swift

let newDirectoryWrapper = LSFileWrapper(directory: ())
let newRegularFileWrapper = LSFileWrapper(file: ())

从磁盘加载

要从磁盘加载现有包装器,请使用 -initWithURL。当布尔值 NO 传递给 isDirectory 时,init 方法会检查并根据传递的 URL 自动创建正确的 LSFileWrapper 类型。

NSURL* url;

LSFileWrapper* existingWrapper = [[LSFileWrapper alloc] initWithURL: url isDirectory: NO];

Swift

let url: URL

let existingWrapper = LSFileWrapper(with: url, isDirectory: false)

写入磁盘

注意: 写入方法应仅在最顶层的包装器上调用 – 即没有父级的包装器。

要将包装器写入磁盘,请调用 -writeToURL-writeUpdatesToURL,两者的区别在于,更新将更新缓存的包装器位置并从内存中删除更改,因此仅在自动保存等情况下使用此方法。对于重复操作,请使用 -writeToURL。只有主包装器可以写入磁盘 – 即没有父级的包装器。如果写入是作为 NSDocument 的保存例程的一部分发出的,则有一个方便的方法 -writeToURL forSaveOperation,它会根据保存操作自动调用 -writeToURL-writeUpdatesToURL,并且还会处理文档备份(版本控制)和另存为时的 URL 切换。

LSFileWrapper* mainWrapper;
NSURL* url;

// Saves all contents to disk at specified URL
[mainWrapper writeToURL: url];

// Dumps all changes to the specified URL, make sure that the LSFileWrapper contents are present at the URL, 
// otherwise the write method could result in partial contents on the disk and potential loss of data.
[mainWrapper writeUpdatesToURL: url];

NSDocument (仅 macOS)

LSFileWrapper* mainWrapper;

-(BOOL)writeToURL:(NSURL *)url forSaveOperation:(NSSaveOperationType)saveOperation originalContentsURL:(NSURL *)absoluteOriginalContentsURL error:(NSError __autoreleasing *)outError {
    [url startAccessingSecurityScopedResource]; // Recommended on OS X 10.7.3 and newer
    BOOL success = [mainWrapper writeToURL: url forSaveOperation: saveOperation originalContentsURL: absoluteOriginalContentsURL backupDocumnetURL: [self backupFileURL] outError: outError];
    [url stopAccessingSecurityScopedResource];
    return success;
}

Swift

let mainWrapper: LSFileWrapper
let url: URL

// Saves all contents to disk at specified URL
mainWrapper.write(to: url)

// Dumps all changes to the specified URL, make sure that the LSFileWrapper contents are present at the URL, 
// otherwise the write method could result in partial contents on the disk and potential loss of data.
mainWrapper.writeUpdates(to: url)

NSDocument (仅 macOS)

let mainWrapper: LSFileWrapper

override func write(to url: URL, for saveOperation: SaveOperationType, originalContentsURL absoluteOriginalContentsURL: URL?) throws {
    _ = url.startAccessingSecurityScopedResource()
    try mainPackageWrapper.write(to: url, for: saveOperation, originalContentsURL: absoluteOriginalContentsURL, backupDocumentURL: self.backupFileURL)
    url.stopAccessingSecurityScopedResource()
}

添加内容

注意: 仅限目录包装器。

要将文件包装器添加到现有目录包装器,请使用 -addFileWrapper-setFileWrapper,两者的区别在于,如果已存在同名包装器,add 会在文件名后添加后缀 2、3、4 等...并返回最终文件名,set 将覆盖任何现有文件包装器。-addContent-setContent 的工作方式相同,但会为您创建文件包装器。

LSFileWrapper* directoryWrapper;

// Adds an empty directory with preferred name
NSString* folderName = [directoryWrapper addFileWrapper: [[LSFileWrapper alloc] initDirectory] withFilename: @"Empty Directory Name"];

// Adds and overrides any wrappers matching the filename
[directoryWrapper setFileWrapper: [[LSFileWrapper alloc] initDirectory] withFilename: @"Empty Directory Name"];

// Adds a new text file
NSString* fileName = [directoryWrapper addContent: @"Hello, World!" withFilename: @"hello.txt"];

// Adds and overrides any files matching the filename. This method could also be used when changes are made to the file
[directoryWrapper setContent: @"Hello, World!" withFilename: @"hello.txt"];

Swift

let directoryWrapper: LSFileWrapper

// Adds an empty directory with preferred name
let folderName = directoryWrapper.add(wrapper: LSFileWrapper(directory: ()) withFilename: "Empty Directory Name")

// Adds and overrides any wrappers matching the filename
directoryWrapper.set(wrapper: LSFileWrapper(directory: ()) withFilename: "Empty Directory Name")

// Adds a new text file. Content has to be of Objective-C type, i.e. NSString, NSData... or casted with `as` operator
let filename = directoryWrapper.add(content: NSString("Hello, World!"), withFilename: "hello.txt")

// Adds and overrides any files matching the filename. This method can be used when changes are made to the file
directoryWrapper.set(content: "Hello, World!" as NSString, withFilename: "hello.txt")

读取内容

注意: 仅限文件包装器。

要检索常规文件包装器的内容,请使用各种便捷方法之一:-data-string-dictionary-image

LSFileWrapper* fileWrapper;

NSData* data = [fileWrapper data];
NSString* string = [fileWrapper string];

Swift

let fileWrapper: LSFileWrapper

let optionalData = fileWrapper.data()
let optionalString = fileWrapper.string()

更新内容

注意: 仅限文件包装器。

要更新常规文件包装器的内容,请使用 -updateContent,在 Swift 中命名为 update(newContent:)

LSFileWrapper* fileWrapper;

[fileWrapper updateContent: @"Hello, World!"];

Swift

let fileWrapper: LSFileWrapper

fileWrapper.update(newContent: "Hello, World!" as NSString)

移除包装器

注意: 仅限目录包装器。

要从现有包装器中删除文件包装器,请使用 -removeFileWrapperremoveFileWrapperWithPath,在 Swift 中命名为 removeWrapper()removeWrapper(with:)

LSFileWrapper* directoryWrapper;

// Using a path, can also contain "/" for subfolder search, all children can be removed
[directoryWrapper removeFileWrapperWithPath: @"hello.txt"];

// Using an instance of a wrapper. Path can also contain "/" for subfolder search, however only 'first' children can be removed.
LSFileWrapper* wrapperToRemove = [directoryWrapper fileWrapperWithPath: @"hello.txt"];
if (wrapperToRemove) {
    [directoryWrapper removeFileWrapper: wrapperToRemove];
}

Swift

let directoryWrapper: LSFileWrapper

// Using a path, can also contain "/" for subfolder search, all children can be removed
directoryWrapper.removeWrapper(with: "hello.txt")

// Using an instance of a wrapper. Path can also contain "/" for subfolder search, however only 'first' children can be removed.
if let wrapperToRemove = directoryWrapper.wrapper(with: "hello.txt") {
    directoryWrapper.removeWrapper(wrapperToRemove)
}

获取子包装器

注意: 仅限目录包装器。

要从目录包装器中获取包装器,请调用 -fileWrapperWithPath,在 Swift 中命名为 wrappers(with:),这也会根据提供的路径遍历所有子级。

LSFileWrapper* directoryWrapper;

LSFileWrapper* wrapper = [directoryWrapper fileWrapperWithPath: @"hello.txt"];

Swift

let directoryWrapper: LSFileWrapper

let wrapper = directoryWrapper.wrapper(with: "hello.txt")

要从目录包装器获取所有一级子包装器,请调用 -fileWrappersInPath,在 Swift 中命名为 wrappers(in:),这也会根据提供的路径遍历所有子级。

LSFileWrapper* directoryWrapper;

NSArray<LSFileWrapper*> *wrappers = [directoryWrapper fileWrappersInPath: @"/"];

Swift

let directoryWrapper: LSFileWrapper

let wrappers = directoryWrapper.wrappers(in: "/")

⚖️ 许可证

LSFileWrapper 在 MIT 许可证下分发。