1

我正在开发一个基于 SwiftUI 文档的应用程序,其中包含一些易于序列化的数据和多个图像。我想将文档保存为一个包(即一个文件夹),其中一个文件包含易于序列化的数据,一个子文件夹包含图像作为单独的文件。我的包目录应该是这样的:

 <UserChosenName.pspkg>/.    // directory package containing my document data and images
       PhraseSet.dat   // regular file with serialized data from snapshot
       Images/              // subdirectory for images (populated directly from my app as needed)
             Image0.png
             Image1.png
             ....

我创建了一个 FileWrapper 子类,它设置目录结构并适当地添加序列化快照,但是当我在 iOS 模拟器中运行应用程序并单击“+”创建一个新文档时,应用程序通过 PkgFileWrapper init() 运行并write() 没有错误,但没有明显地创建任何东西就返回浏览器窗口。我已经声明导出和导入类型标识符符合“com.apple.package”。任何人都可以建议一种方法来使其正常工作吗?

PkgFileWrapper 类如下所示:

class PkgFileWrapper: FileWrapper {

var snapshot: Data

init(withSnapshot: Data) {
    self.snapshot = withSnapshot
    let sWrapper = FileWrapper(regularFileWithContents: snapshot)
    let dWrapper = FileWrapper(directoryWithFileWrappers: [:])
    super.init(directoryWithFileWrappers: ["PhraseSet.dat" : sWrapper,
                                           "Images" : dWrapper ])
    
    // NOTE: Writing of images is done outside
    // of the ReferenceFileDocument functionality.
}
    
override func write(to: URL,
                    options: FileWrapper.WritingOptions,
                    originalContentsURL: URL?) throws {
    try super.write(to: to, options: options,
                    originalContentsURL: originalContentsURL)
}

required init?(coder inCoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

}

4

1 回答 1

1

解决方案是不覆盖 PkgFileWrapper.write(...)。如果在 init(...) 中正确设置了目录结构,则将自动创建文件和目录。上面重写的 write(...) 函数现已更正。

如果要将图像写入图像子目录,可以执行以下操作:

func addImage(image: UIImage, name: String) {
    let imageData = image.pngData()!
    imageDirWrapper.addRegularFile(withContents: imageData,
                               preferredFilename: name)

}

imageDirWrapper 的值是与保存图像的目录相对应的目录包装器,如上面的 PkgFileWrapper.init() 中创建的。您需要记住的一个关键概念是“写入”函数将在适当的时间自动调用 - 您无需明确写出图像数据。ReferenceFileDocument 类将为此安排,还将安排为您的应用传递适当的 URL 以设置您的文件包装器。

imageDirWrapper 变量在 ReferenceFileDocument 协议所需的 init(...) 中设置:

required init(configuration: ReadConfiguration) throws {
    phraseSet = PhraseSet()
    
    
    if configuration.file.isDirectory {
        if let subdir = configuration.file.fileWrappers {
            
            // first load in the phraseSet
            for (name, wrapper) in subdir {
                if name == PkgFileWrapper.phraseSetFileName {
                    if let data = wrapper.regularFileContents {
                        phraseSet = try PhraseSet(json: data)
                    }
                }
            }
            
            // next load in the images and put them into the phrases.
            for (name, wrapper) in subdir {
                if name == PkgFileWrapper.imageDirectoryName {
                    if let imageDir = wrapper.fileWrappers {
                        imageDirWrapper = wrapper
                        for (iName, iWrapper) in imageDir {
                            print("image file: \(iName)")
                            if let d = iWrapper.regularFileContents {
                                for p in phraseSet.phrases {
                                    if p.imageName == iName {
                                        
                                        // TBD: downsample

                                        var uiD = ImageData(data: d)
                                        if doDownSample {
                                            uiD.uiimageData = downsample(data: d,
                                                                         to: imageSize)
                                        } else {
                                            _ = uiD.getUIImage()
                                        }
                                        images[iName] = uiD
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    } else {
        throw CocoaError(.fileReadCorruptFile)
    }

您可以在此处查看 imageDirWrapper 的设置方式,方法是查看传入目录的子目录中的图像目录名称。还有一些额外的代码:它首先在传入的目录中查找数据文件并将其加载;然后它查找图像目录并处理它。

于 2021-07-21T23:59:31.207 回答