【问题标题】:Generic functions for multiple CoreData entities多个 CoreData 实体的通用函数
【发布时间】:2023-04-08 17:28:01
【问题描述】:

我目前正在开发一个跟踪 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?()
        }
    }
...
}

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

【问题讨论】:

    标签: swift generics core-data codable


    【解决方案1】:

    您基本上可以创建一个 PAT,它的类型又是一个协议,并使用泛型提取您的通用函数。像这样的,

    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,这可能会变得非常混乱。最好避免它们并考虑其他一些设计因素,因为它会使代码更复杂且难以理解。但是,如果您可以限制设计的范围,那么您就可以很好地使用此解决方案。

    【讨论】:

    • 谢谢,我会考虑我的选择,看看什么最适合代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多