我想知道在Core Data中存储3D模型是否有效且有意义?如果不是,最佳解决方案是什么?比如Firebase之类的我目前正在使用CoreData,但我担心如果用户导入更大的模型,存储和性能会受到影响。
jmp7cifd1#
我不认为核心数据会对整个过程产生任何明显的性能影响。这个过程是导入/下载大文件或数据块,然后存储,然后在应用程序中读取、解析和使用。在核心数据模型中,您可以有一个带“允许外部存储”选项的Binary Data类型字段。这是为了将您的数据(在需要时)存储为外部文件。在实际访问项的属性之前,不会加载该文件。即使在您访问它之后,它也应该返回data as mapped文件,以便内存消耗最小。但另一方面,我认为首先使用数据库没有好处。一个数据库只有在你可以期待大量的项目,引入关系和更多的时候才会派上用场。如果你需要使用fetched结果控制器或使用查询来获取基于过滤器(如搜索文本)的项目,它将派上用场。而这些都不能在二进制数据上实现。如果你的项目确实包含一些元数据,例如你的模型有标签、作者和注解等等,那么把这些数据放到数据库中并从数据库提供的一切中受益是很好的。之后,您仍然可以选择将二进制数据保留在数据库中,或者使用普通文件保存二进制数据,同时将文件名保存在数据库中。一般来说,处理文件需要一点努力,但不会太多。可能比实现任何数据库都要少。一个快速实现可能类似于以下内容
class ModelsFileManager { struct ModelMetadata: Codable { fileprivate let localID: UUID let name: String let author: String let tags: [String] } let modelPathExtension: String = "3DModel" let metadataPathExtension: String = "3DModelMetadata" let folderName: String private let directoryPath: URL init(folderName: String = "3D models") { self.folderName = folderName directoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appending(component: folderName) } private func modelPathWithID(_ id: UUID) -> URL { directoryPath.appendingPathComponent(id.uuidString).appendingPathExtension(modelPathExtension) } private func metadataPathWithID(_ id: UUID) -> URL { directoryPath.appendingPathComponent(id.uuidString).appendingPathExtension(metadataPathExtension) } func insertNewModel(file: URL, modelInfo: (name: String, author: String, tags: [String])) throws { let metadata = ModelMetadata(localID: .init(), name: modelInfo.name, author: modelInfo.author, tags: modelInfo.tags) if !FileManager.default.fileExists(atPath: directoryPath.path) { try FileManager.default.createDirectory(at: directoryPath, withIntermediateDirectories: true) } try FileManager.default.moveItem(at: file, to: modelPathWithID(metadata.localID)) let metadataFile = try JSONEncoder().encode(metadata) try metadataFile.write(to: metadataPathWithID(metadata.localID)) } func loadAllMetadata() throws -> [ModelMetadata] { try FileManager.default.contentsOfDirectory(at: directoryPath, includingPropertiesForKeys: nil) .filter { $0.pathExtension == metadataPathExtension } .compactMap { let data = try Data(contentsOf: $0) return try? JSONDecoder().decode(ModelMetadata.self, from: data) } } func modelPathForMetadata(_ metadata: ModelMetadata) -> URL { modelPathWithID(metadata.localID) } }
字符串我们的想法是将您的模型下载到一个临时目录,然后使用insetNewModel移动它,并附加所有信息。在此之后,loadAllMetadata应该会给予你所有的权力来访问和管理你的模型和其他信息。您可以获取模型的URL,然后根据需要将其转换为Data。
insetNewModel
loadAllMetadata
Data
1条答案
按热度按时间jmp7cifd1#
我不认为核心数据会对整个过程产生任何明显的性能影响。这个过程是导入/下载大文件或数据块,然后存储,然后在应用程序中读取、解析和使用。
在核心数据模型中,您可以有一个带“允许外部存储”选项的Binary Data类型字段。这是为了将您的数据(在需要时)存储为外部文件。在实际访问项的属性之前,不会加载该文件。即使在您访问它之后,它也应该返回data as mapped文件,以便内存消耗最小。
但另一方面,我认为首先使用数据库没有好处。一个数据库只有在你可以期待大量的项目,引入关系和更多的时候才会派上用场。如果你需要使用fetched结果控制器或使用查询来获取基于过滤器(如搜索文本)的项目,它将派上用场。而这些都不能在二进制数据上实现。
如果你的项目确实包含一些元数据,例如你的模型有标签、作者和注解等等,那么把这些数据放到数据库中并从数据库提供的一切中受益是很好的。之后,您仍然可以选择将二进制数据保留在数据库中,或者使用普通文件保存二进制数据,同时将文件名保存在数据库中。
一般来说,处理文件需要一点努力,但不会太多。可能比实现任何数据库都要少。一个快速实现可能类似于以下内容
字符串
我们的想法是将您的模型下载到一个临时目录,然后使用
insetNewModel
移动它,并附加所有信息。在此之后,loadAllMetadata
应该会给予你所有的权力来访问和管理你的模型和其他信息。您可以获取模型的URL,然后根据需要将其转换为Data
。