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)
注意: 仅限目录包装器。
要从现有包装器中删除文件包装器,请使用 -removeFileWrapper
或 removeFileWrapperWithPath
,在 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 许可证下分发。