微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Swift 5:将复杂对象保存到文件存储

如何解决Swift 5:将复杂对象保存到文件存储

我正在处理学校作业,必须在Swift 5中开发一个iOS应用程序。该应用程序需要利用Web服务(Web API)以及文件存储或用户认设置。

我选择开发“ QR代码管理器”,用户可以通过设置一些设计参数来为URL创建QR代码,然后将其发送到生成器API。此API(根据“确定”请求)以指定的格式(以我的情况为PNG)返回图像。

我有一个包含URL和QR码所有设计属性的类,其中还将包含图像本身。请参见下面的代码段。

public class QRCode {
    
    var bsId : Int?
    var url : String?
    var name: String?
    var frame: Frame?
    var logo: QrCodelogo?
    var marker: Marker?
    var color : String?
    var bgColor : String?
    var image : Data?
    
    
    init(data: [String:String]) {
        self.url = data["url"]
        self.frame = Frame.allCases.first(where: { $0.description == data["frame"] })
        self.logo = QrCodelogo.allCases.first(where: { $0.description == data["logo"] })
        self.marker = Marker.allCases.first(where: { $0.description == data["marker"] })
        self.bgColor = data["backGroundColor"]
        self.color = data["colorLight"]
    }
    
    init(json: String) {
        // todo
    }
}

extension QRCode {
    func toDict() -> [String:Any] {
        var dict = [String:Any]();
        let otherSelf = Mirror(reflecting: self);
        for child in otherSelf.children {
            if let key = child.label {
                dict[key] = child.value;
            }
        }
        return dict;
    }
}

为了易于开发,所有属性都可以为空,一旦我成功实现了所有内容,该类将被进一步重构。

我尝试了在互联网上找到的各种方法,其中一种可以在类扩展中找到。函数toDict()将对象属性及其值转换为类型Dictionary的{​​{1}}对象。但是,我读到[String:Any]数据类型经过编码然后解码时,Swift无法确定解码后的数据应该是哪种复杂数据类型,从而使数据变得毫无意义或无法使用。

我发现的另一种方法是通过扩展类中的Any协议。据我所知,Codable仅接受原始数据类型。

请在下面找到我当前编写的用于文件存储处理的代码。尚未完成,但是我觉得这是一个不错的开始,可能会在这个问题上有所帮助。

Codable

我对Swift还是很陌生,并且我卡在文件存储上。有什么方法可以将此类的实例存储在文件存储中,以便在检索数据时可以重新实例化此类?

提前谢谢!如果有任何疑问,请不要犹豫。

编辑

根据马特的评论,请在下面找到 class StorageManager { fileprivate let filemanager: FileManager = FileManager.default; fileprivate func filePath(forKey key: String) -> URL? { guard let docURL = filemanager.urls(for: .documentDirectory,in: FileManager.SearchPathDomainMask.userDomainMask).first else { return nil; } return docURL.appendingPathComponent(key); } func writetoStorage(identifier: String,data: QRCode) -> Void { guard let path = filePath(forKey: identifier) else { throw ApplicationErrors.runtimeError("Something went wrong writing the file to storage"); } let dict = data.toDict(); // Todo:: Implement } func readFromStorage(identifier: String) -> Any { // Todo:: Implement return 0; } func readAllFromStorage() throws -> [URL] { let docsURL = filemanager.urls(for: .documentDirectory,in: .userDomainMask)[0]; do { let fileURLs = try filemanager.contentsOfDirectory(at: docsURL,includingPropertiesForKeys: nil); return fileURLs; } catch { throw ApplicationErrors.runtimeError("Something went wrong retrieving the files from \(docsURL.path): \(error.localizedDescription)"); } } } MarkerFrame枚举的代码段。 QrCodelogo枚举:

Frame

public enum Frame: String,CaseIterable { case noFrame case bottomFrame case bottomTooltip case topHeader static var count: Int { return 4 } var description: String { switch self { case .noFrame: return "no-frame" case .bottomFrame: return "bottom-frame" case .bottomTooltip: return "bottom-tooltip" case .topHeader: return "top-header" } } } 枚举:

QrCodelogo

public enum QrCodelogo: String,CaseIterable { case nologo case scanMe case scanMeSquare static var count: Int { return 3 } var description: String { switch self { case .nologo: return "no-logo" case .scanMe: return "scan-me" case .scanMeSquare: return "scan-me-square" } } } 枚举:

Marker

以上所有枚举都包含我使用的API的有效设计选项。它们用作输入限制,以防止发生“无效参数”错误

希望这可以清除一切。

再次感谢!

解决方法

只要类型的所有属性都符合Codable,则该类型可以符合Codable。您的所有属性 do 都符合Codable,但枚举除外;如果您声明它们符合,则它们将符合Codable。这样,您的类型的这一简单草图即可进行编译:

public enum Frame: String,Codable {
    case noFrame
    case bottomFrame
    case bottomTooltip
    case topHeader
}
public enum QrCodeLogo: String,Codable {
    case noLogo
    case scanMe
    case scanMeSquare
}
public enum Marker: String,Codable {
    case version1
    case version2
    case version3
    case version4
    case version5
    case version6
    case version7
    case version8
    case version9
    case version10
    case version11
    case version12
    case version13
    case version15
    case version16
}
public class QRCode : Codable {
    var bsId : Int?
    var url : String?
    var name: String?
    var frame: Frame?
    var logo: QrCodeLogo?
    var marker: Marker?
    var color : String?
    var bgColor : String?
    var image : Data?
}

您的代码还有很多其他可以改进的地方。 您不需要CaseIterable或description。现在您的类型是可编码的,您可以使用 it 直接从JSON直接自动检索值。如果您的枚举案例的名称与相应的JSON键不匹配,则只需制作一个CodingKey嵌套枚举即可充当桥梁。

换句话说,可编码使得您的类型两者都可以直接从JSON 填充,并且可以序列化到磁盘。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。