iOS ObjectMapper 增量更新
iOS ObjectMapper incremental updating
我的项目有问题,当我的应用程序启动时,配置会自动从服务器更新,json 从服务器像这样:
{
"version":1
"config":
{
"key1": {xxx}
"key2": {xxx}
"key3": {xxx}
"key4": {xxx}
"key5": {xxx}
"key6": {xxx}
}
然后我使用 ObjectMapper
将 json 转换为模型,如下所示:
struct GlobalConfig: Mappable {
var version = 0
var key1: [String: [LocalizedText]]?
var key2: [RouteObject]?
var key3: UrlConfig?
var key4: [String: [String: [[String: Any]]]]?
var key5: DegreeInfoList?
var key6: [String: String]?
init?(map: Map) { }
mutating func mapping(map: Map) {
version <- map["version"]
key1 <- map["key1"]
key2 <- map["key2"]
key3 <- map["key3"]
key4 <- map["key4"]
key5 <- map["key5"]
key6 <- map["key6"]
}
现在有个问题,当来自服务器的json很大时,会消耗很多流量。事实上,有些配置不需要更新。所以来自服务器的 json 会像这样:
{
"version":2
"config":
{
"key1": {xxx}
"key2": {xxx}
}
表示key1
和key2
会更新,key3
、key4
、key5
和key6
保持旧值。
如何处理JSON?
我不明白 Mapper
对象是什么。可以用 Codable
.
来完成
您可以这样做以使用传入的配置更新您的本地配置。
struct GlobalConfig: Codable {
var version = 0
var key1: [String: [LocalizedText]]?
var key2: [RouteObject]?
var key3: UrlConfig?
var key4: [String: [String: [[String: Any]]]]?
var key5: DegreeInfoList?
var key6: [String: String]?
mutating func combine(with config: GlobalConfig) {
if let k = config.key1 { key1 = k }
if let k = config.key2 { key2 = k }
...
}
}
class App {
var config: GlobalConfig
func receiveConfig(newConfig: GlobalConfig) {
config.combine(with: newConfig)
}
}
已编辑:
作为对评论的回应,这里是 'deep' 组合的可能解决方案。
非常粗略:
extension Dictionary {
func combine(with dictionary: Dictionary) {
}
}
extension Array {
func combine(with array: Array) {
}
}
protocol Combinable: Codable {
func combine(with object: Self)
}
struct GlobalConfig: Combinable {
var version = 0
var key1: [String: [LocalizedText]]?
var key2: [RouteObject]?
mutating func combine(with config: GlobalConfig) {
if let k = config.key1 { key1.combine(with: k) }
if let k = config.key2 { key2.combine(with: k) }
...
}
}
这是另一个主题,但应避免使用 [String: [String: [[String: Any]]]]
之类的类型。
很难阅读、调试和组合 ;)
我认为使用结构化子模型更好。更安全、可扩展且 'documentable'.
struct GlobalConfig: Codable {
...
// Old format: var key4: [String: [String: [[String: Any]]]]?
var key4: MegaSettings?
...
}
struct MegaSettings: Combinable {
struct ScreenOptions: Combinable {
var options: [String: Any]
}
struct DisplayOptions: Combinable {
struct DeviceDisplayOptions {
var screen: [ScreenOptions]
}
var optionsPerDevice: [String: DeviceDisplayOptions]
}
var displayOptions: [String: DisplayOptions]
}
我的项目有问题,当我的应用程序启动时,配置会自动从服务器更新,json 从服务器像这样:
{
"version":1
"config":
{
"key1": {xxx}
"key2": {xxx}
"key3": {xxx}
"key4": {xxx}
"key5": {xxx}
"key6": {xxx}
}
然后我使用 ObjectMapper
将 json 转换为模型,如下所示:
struct GlobalConfig: Mappable {
var version = 0
var key1: [String: [LocalizedText]]?
var key2: [RouteObject]?
var key3: UrlConfig?
var key4: [String: [String: [[String: Any]]]]?
var key5: DegreeInfoList?
var key6: [String: String]?
init?(map: Map) { }
mutating func mapping(map: Map) {
version <- map["version"]
key1 <- map["key1"]
key2 <- map["key2"]
key3 <- map["key3"]
key4 <- map["key4"]
key5 <- map["key5"]
key6 <- map["key6"]
}
现在有个问题,当来自服务器的json很大时,会消耗很多流量。事实上,有些配置不需要更新。所以来自服务器的 json 会像这样:
{
"version":2
"config":
{
"key1": {xxx}
"key2": {xxx}
}
表示key1
和key2
会更新,key3
、key4
、key5
和key6
保持旧值。
如何处理JSON?
我不明白 Mapper
对象是什么。可以用 Codable
.
您可以这样做以使用传入的配置更新您的本地配置。
struct GlobalConfig: Codable {
var version = 0
var key1: [String: [LocalizedText]]?
var key2: [RouteObject]?
var key3: UrlConfig?
var key4: [String: [String: [[String: Any]]]]?
var key5: DegreeInfoList?
var key6: [String: String]?
mutating func combine(with config: GlobalConfig) {
if let k = config.key1 { key1 = k }
if let k = config.key2 { key2 = k }
...
}
}
class App {
var config: GlobalConfig
func receiveConfig(newConfig: GlobalConfig) {
config.combine(with: newConfig)
}
}
已编辑:
作为对评论的回应,这里是 'deep' 组合的可能解决方案。
非常粗略:
extension Dictionary {
func combine(with dictionary: Dictionary) {
}
}
extension Array {
func combine(with array: Array) {
}
}
protocol Combinable: Codable {
func combine(with object: Self)
}
struct GlobalConfig: Combinable {
var version = 0
var key1: [String: [LocalizedText]]?
var key2: [RouteObject]?
mutating func combine(with config: GlobalConfig) {
if let k = config.key1 { key1.combine(with: k) }
if let k = config.key2 { key2.combine(with: k) }
...
}
}
这是另一个主题,但应避免使用 [String: [String: [[String: Any]]]]
之类的类型。
很难阅读、调试和组合 ;)
我认为使用结构化子模型更好。更安全、可扩展且 'documentable'.
struct GlobalConfig: Codable {
...
// Old format: var key4: [String: [String: [[String: Any]]]]?
var key4: MegaSettings?
...
}
struct MegaSettings: Combinable {
struct ScreenOptions: Combinable {
var options: [String: Any]
}
struct DisplayOptions: Combinable {
struct DeviceDisplayOptions {
var screen: [ScreenOptions]
}
var optionsPerDevice: [String: DeviceDisplayOptions]
}
var displayOptions: [String: DisplayOptions]
}