gpt4 book ai didi

swift - Realm :部分更新

转载 作者:行者123 更新时间:2023-11-30 10:08:28 25 4
gpt4 key购买 nike

我在 Swift 项目中使用 Realm ,但在部分更新对象时遇到问题。

问题是我有一个对象,其中包含来自服务器的信息加上用户生成的信息。就我而言,它是一个默认情况下可见或隐藏的主题,但用户可以更改可见性值。

当我第一次启动应用程序时,我调用服务器 API 来获取信息以创建 Topic 对象:它的 visibilityundefined 。然后用户做出选择并将 visibility 值设置为 visible

第二次启动应用程序时,我再次从服务器获取信息并重新创建主题。然后,我调用 Realm 方法 add:update: 来更新对象,但这甚至将 visibility 属性再次更新为 undefined

我知道还有另一种方法 create:value:update: 但这意味着我必须创建一个包含我想要更新的所有值的大字典。我的模型对象不是那么小,在某些情况下我有很多属性,字典会很大。我不喜欢这种方法,维护起来很复杂。

您对如何处理此类案件有任何提示吗?

一种可能的方法是创建另一个与主题有关系的对象(表)和一个属性可见性,当我再次创建主题时,该属性不会被覆盖,但专门为这个东西创建一个表听起来很奇怪。

最佳答案

我的服务端点的运行方式也遇到了类似的问题。它提供了完整的实体 View ,以及该实体上属性的较小 View ,我想在它们被击中时更新模型。示例:

class User: Object {
var id: Int
var name: String
var age: Int
var average: Double
likes: List<User>
}

一个端点获取全部 4 个字段,另一个端点仅获取 averageid ,只有第三个 likesid ,但是我想从其中任何一个创建/更新模型。现在,我可以使用 create(value:update:)在返回的原始 JSON 上,但是我的模型映射了不同的键名,并执行了我想要保留的其他转换操作(以及日期和其他操作),因此无法仅调用 create(value:update:)与 JSON 字典。

我们通过利用反射和名为 Serializable 的协议(protocol)来解决这个问题,看起来像这样:

protocol Serializable {
func toDictionary() -> [String: Any]
}

extension Serializable {
func toDictionary() -> [String: Any] {
var propertiesDictionary: [String: Any] = [:]
let mirror = Mirror(reflecting: self)
for (propName, propValue) in mirror.children {
guard let propName = propName else { continue }
// Attempt to unwrap the value as AnyObject
if let propValue: AnyObject = self.unwrap(propValue) as AnyObject? {
switch propValue {
case let serializablePropValue as Serializable:
propertiesDictionary[propName] = serializablePropValue.toDictionary()
case let arrayPropValue as [Serializable]:
propertiesDictionary[propName] = Array(arrayPropValue.flatMap { $0.toDictionary() })
case let data as Data:
propertiesDictionary[propName] = data.base64EncodedString(options: .lineLength64Characters)
case _ as Bool: fallthrough
case _ as Int: fallthrough
case _ as Double: fallthrough
case _ as Float: fallthrough
default:
propertiesDictionary[propName] = propValue
}
} else {
// Couldn't treat as AnyObject, treat as Any
switch propValue {
case let arrayPropValue as [Serializable]:
propertiesDictionary[propName] = arrayPropValue.flatMap { $0.toDictionary() }
case let primative as Int8: propertiesDictionary[propName] = primative
case let primative as Int16: propertiesDictionary[propName] = primative
case let primative as Int32: propertiesDictionary[propName] = primative
case let primative as Int64: propertiesDictionary[propName] = primative
case let primative as UInt8: propertiesDictionary[propName] = primative
case let primative as UInt16: propertiesDictionary[propName] = primative
case let primative as UInt32: propertiesDictionary[propName] = primative
case let primative as UInt64: propertiesDictionary[propName] = primative
case let primative as Float: propertiesDictionary[propName] = primative
case let primative as Double: propertiesDictionary[propName] = primative
case let primative as Bool: propertiesDictionary[propName] = primative
case let primative as String: propertiesDictionary[propName] = primative
case let primative as Date: propertiesDictionary[propName] = primative
case let primative as Data: propertiesDictionary[propName] = primative
default: break
}
}
}
return propertiesDictionary
}
/// Unwraps 'any' object.
/// See http://stackoverflow.com/questions/27989094/how-to-unwrap-an-optional-value-from-any-type
/// - parameter any: Any, Pretty clear what this is....
/// - returns: The unwrapped object.
private func unwrap(_ any: Any) -> Any? {
let mi = Mirror(reflecting: any)
guard let displayStyle = mi.displayStyle else { return any }
switch displayStyle {
case .optional:
if mi.children.count == 0 {
return nil
}
if let (_, some) = mi.children.first {
return some
} else {
return nil
}
case .enum:
let implicitTypes: [Any.Type] = [ImplicitlyUnwrappedOptional<Int>.self,
ImplicitlyUnwrappedOptional<String>.self,
ImplicitlyUnwrappedOptional<Double>.self,
ImplicitlyUnwrappedOptional<Bool>.self,
ImplicitlyUnwrappedOptional<Float>.self,
ImplicitlyUnwrappedOptional<Date>.self]
if implicitTypes.contains(where: { $0 == mi.subjectType }) {
if mi.children.count == 0 { return nil }
if let (_, some) = mi.children.first {
return some
} else {
return nil
}
}
return any
default: return any
}
}

通过这个,您可以序列化部分填充的对象,然后传递 create(value: obj.toDictionary(), update: true)

需要注意的几个注意事项:RealmOptional<T> , List<T> ,和LinkingObjects<T>此处未处理,您可以为 RealmOptional<T> 添加显式基元类型的情况, LinkingObjectsBase 的跳过案例,以及带有自定义处理的跳过案例 ListBase (反射/不/与列表配合得很好:/)

关于swift - Realm :部分更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34661183/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com