Plist 使用可编码和静态变量构造 class

Plist to struct class with codable and static variables

我有一个 Plist,其中包含端点 URL。我想在应用程序打开后读取该 Plist 并将其写入我的 URL 结构,并且我想在任何地方访问这些 URL。因此,变量需要是静态的。但是,当我执行 var's static 时,出现以下错误;

'static var' declaration requires an initializer expression or getter/setter specifier.

struct URLs: Codable {
        static let urlBaseURL: String
        static let urlCheckCMS: String
        static let urlJSON: String

        enum CodingKeys: String, CodingKey {
            case urlBaseURL = "url_base_url"
            case urlCheckCMS = "url_check_cms"
            case urlJSON = "url_json"
        }
    }

    // MARK: Convenience initializers

    extension URLs {
        init?(data: Data) {
            guard let me = try? PropertyListDecoder().decode(URLs.self, from: data) else { return nil }
            self = me
        }

        init?(_ plist: String, using encoding: String.Encoding = .utf8) {
            guard let data = plist.data(using: encoding) else { return nil }
            self.init(data: data)
        }

        init?(fromURL url: String) {
            guard let url = URL(string: url) else { return nil }
            guard let data = try? Data(contentsOf: url) else { return nil }
            self.init(data: data)
        }

        var plistData: Data? {
            return try? JSONEncoder().encode(self)
        }

        var plist: String? {
            guard let data = self.plistData else { return nil }
            return String(data: data, encoding: .utf8)
        }

编辑:除了下面的答案之外,我用下面的代码更改数据初始化 class 以摆脱可选。使用下面的代码,我检查了 plist 和 If return nil when creating init class app won't continue to work;

    init?(data: Data) {
    guard let me = try? PropertyListDecoder().decode(URLs.self, from: data) else { return nil }
    self = me
    URLs.instance = me
}

static var instance: URLs!

但我仍然不确定这是否是最佳方法。如下所述 post;

Loading Configurations from plist into singleton

要修复编译器错误,您应该只为静态成员提供一个默认值:

static let urlBaseURL: String = ""

但是,您的代码存在一些主要问题。在可编码结构中使用静态成员不会像您想象的那样工作,因为 coding/encoding 总是在结构的 实例 上运行,而不是在结构类型本身上运行。

您应该从您的变量中删除 static,而是提供一个 URLs 的单例实例,然后可以从您应用的所有组件中读取它:

struct URLs: Codable {
  static var instance? = nil
  let urlBaseURL: String
  let urlCheckCMS: String
  let urlJSON: String
}

在您的启动代码中,您可以设置值:

URLs.instance = URLs(data: yourData)

稍后您可以访问以下值:

let urlBaseURL = URLs.instance?.urlBaseURL

请注意,单例模式经常受到批评,而且有充分的理由;对于你的情况,首先我认为没关系。