使用可编码和静态变量对结构化类进行Plist

时间:2018-01-23 07:44:53

标签: ios swift static plist codable

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

  

' static var'声明需要初始化表达式或getter / setter说明符。

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)
        }

编辑:除了以下答案,我用下面的代码更改数据init类,以摆脱可选。使用下面的代码,我检查plist,如果在创建init class app时返回nil,则不会继续工作;

    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!

但我仍然不确定这是最好的方法。正如下文所讨论的那样;

Loading Configurations from plist into singleton

1 个答案:

答案 0 :(得分:1)

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

static let urlBaseURL: String = ""

但是,您的代码存在一些主要问题。在可编码结构中使用静态成员将无法正常工作,因为编码/编码始终在结构的实例上运行,而不是在结构类型本身上运行。

您应该从vars中删除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

请注意,单身模式通常受到批评,并且有充分的理由;在你的情况下,一开始我觉得没关系。