swift - 多个 CoreData 实体的通用函数

标签 swift generics core-data codable

我目前正在开发一个跟踪 5 个 CoreData 实体并与服务器同步的应用程序,到目前为止我一直在做一些自定义类用于同步和相应的 Codable 结构来上传和接收信息服务器。我为每个实体开发了一个扩展,以将信息从 Codable 结构映射到 CoreData 实体。


我的问题是我有这 5 个类,它们做的完全一样,实体和结构略有变化,我很想做一个通用的 Class 来保持信息同步只需添加 URL 参数即可。但我得到的问题是,因为所有实体由于它们自己的变量而以不同方式映射信息,所以我不能使用 NSManagedObject 的通用参数,因为它无法识别扩展功能,这里是一个简单的例子:


类示例:

class SincronizacionCampos{
...
     /**
     Eliminar los campos seleccionados de la nube

     Se envían los ids de los campos que deben de ser eliminados de la nube personal del usuario

     - Parameters:
        - ids: Lista de los ids de los campos que deben de ser eliminados
        - salida: Llamada al terminar la ejecución de la solicitud
     */
    fileprivate func eliminar(ids: Set<Int32>?, o informacion: [CampoSerializer]?, _ salida: (()->())? = nil){
        guard let token = InfoUsuario.shared.token else{
            salida?()
            return
        }
        let lista = ListaCamposSerializer()
        lista.campos = [CampoSerializer]()
        if let info = informacion {
            lista.campos = info
        } else{
            ids?.forEach { (id) in
                let ser = CampoSerializer.init(id: id, uuid: nil, verificado: false, hcpIguales: false, nombre: "", sumaPar: 0, par: "", hcp1: "", hcp2: "", colorHandicap1: 0, colorHandicap2: 0, idDeUsuario: nil, nombreDeUsuario: nil)
                lista.campos?.append(ser)
            }
        }
        ConexionServer.shared.solicitudDELETE(con: .camposDePerfil, parametros: lista, token: token, desde: nil) { (hayError, descripcion) in
            guard hayError == false else{
                Logging.shared.escribirNuevo(descripcion)
                salida?()
                return
            }
            salida?()
        }
    }
...

在我的 Amigos 类中有同样的功能:

class SincronizacionAmigos{
...
     /**
     Eliminar jugadores del servidor

     Envia una solicitud al servidor para eliminar los jugadores que han sido eliminados localmente.

     - Parameters:
         - ids: Set de IDs de los jugadores que han sido eliminados
         - salida: Llamada al terminar la solicitud
     */
    fileprivate func eliminar(ids: Set<Int32>?, o informacion: [AmigosSerializer]?, _ salida: (()->())? = nil){
        guard let token = InfoUsuario.shared.token else{
            salida?()
            return
        }
        let lista = ListaAmigosSerializer()
        lista.amigos = [AmigosSerializer]()
        if let info = informacion{
            lista.amigos = info
        } else{
            ids?.forEach { (id) in
                let ser = AmigosSerializer.init(id: id, nombreCompleto: nil, nombreCorto: "", ventaja: 0, casados: false, ultimaActualizacion: nil, apuestas: "", numeroDeTelefono: nil, uuid: nil, idJugadorCloud: nil)
                lista.amigos?.append(ser)
            }
        }
        ConexionServer.shared.solicitudDELETE(con: .amigosDePerfil, parametros: lista, token: token, desde: nil) { (hayError, descripcion) in
            guard hayError == false else{
                Logging.shared.escribirNuevo(descripcion)
                guard let pendientes = lista.amigos else{
                    salida?()
                    return
                }
                self.agregarSolicitudFallida(informacion: pendientes, con: .DELETE)
                salida?()
                return
            }
            salida?()
        }
    }
...
}

这只是一个简短的例子,但这个例子的想法是我不能使用相同的序列化器,因为序列化器是不同的。如果有人能给我指出正确的方向,我将不胜感激,如果您需要任何额外信息,请直接说出来,谢谢。

最佳答案

您基本上可以创建一个 PAT,其类型又是一个协议(protocol),并使用泛型提取您的常用功能。像这样,

protocol AnotherSerializer: class {
}

protocol Serializer: class {
    associatedtype SerializerType: AnotherSerializer

    var list: [SerializerType] { set get }

    init()

}

并且您的同步类将具有这样的通用函数,

class Sincronizacion {

    fileprivate func eliminar<T: Serializer, U>(type: T.Type, ids: Set<Int32>?, o informacion: [U]?, _ salida: (()->())? = nil) where T.SerializerType == U {
        guard let token = InfoUsuario.shared.token else{
            salida?()
            return
        }
        let lista = T()
        lista.list = [U]()

        if let info = informacion {
            lista.list = info
        } else {
            // other code here
            }
        }


    }

}

请注意,如果您再次将 AnotherSerializer 设为 PAT,这可能会变得非常困惑。最好避免使用它们并进行一些其他设计考虑,因为它会使代码更加复杂和难以理解。但是,如果您可以限制设计的范围,那么您就非常适合使用此解决方案。

关于swift - 多个 CoreData 实体的通用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57468534/

相关文章:

ios - 使用计时器安排通知触发

swift - 敌人受到多重伤害 - Swift、Xcode 8.2.1

java - 泛型方法]在JAVA中扩展多种类型参数

ios - Swift:植入 Core Data 数据模型的最简单方法

ios - 在堆栈上嵌入 2 个或更多导航 Controller

ios - Swift 3 - Label.Text 的 DateComponents 有时会显示 "..."

c# - 在 Lazy<T> 中转换接口(interface)类型

java - 在这种情况下如何声明和使用通用映射

ios - 如何在 NSManagedObjects 的集合(NSArray 或 NSSet)上设置 KVO

mysql - 核心数据和 MySQL