Comment puis-je facilement dupliquer/copier un objet existant
j'ai un objet Realm qui a plusieurs relations, n'importe qui a un bon snippet de code qui généralise une méthode de copie, pour créer un duplicate dans la base de données.
4 réponses
Dans mon cas, je voulais juste créer un objet et de ne pas persister. donc
Swift 3
pour créer un clone d'objet utilisateur dans swift
il suffit d'utiliser
let newUser = User(value: oldUser)
;
le nouvel objet utilisateur ne persiste pas.
Vous pouvez utiliser les méthodes suivantes pour créer une copie de votre objet, tant que ce n'est pas une clé primaire:
realm.create(ObjectType.self, withValue: existingObject)
j'ai eu le même problème et trouvé une solution simple pour obtenir une copie d'un royaume de l'objet. Fondamentalement, vous avez juste besoin de rendre l'objet conforme au protocole NSCopying, quelque chose comme:
import RealmSwift
import Realm
import ObjectMapper
class Original: Object, NSCopying{
dynamic var originalId = 0
dynamic var firstName = ""
dynamic var lastName = ""
override static func primaryKey() -> String? {
return "originalId"
}
init(originalId: Int, firstName: String, lastName: String){
super.init()
self.originalId = originalId
self.firstName = firstName
self.lastName = lastName
}
func copy(with zone: NSZone? = nil) -> Any {
let copy = Original(originalId: originalId, firstName: firstName, lastName: lastName)
return copy
}
}
alors vous appelez juste la méthode "copy ()" sur l'objet:
class ViewController: UIViewController {
var original = Original()
override func viewDidLoad() {
super.viewDidLoad()
var myCopy = original.copy()
}
}
ce qui est bien d'avoir une copie, c'est que je peux la modifier sans avoir à être dans une transaction d'écriture de domaine. Utile lorsque les utilisateurs éditent certaines données mais n'ont pas encore cliqué sur Enregistrer ou ont simplement changé leur esprit.
comme ce problème est toujours vivant, je poste ma solution qui fonctionne mais doit encore être améliorée.
J'ai créé une extension de classe objet qui a cette méthode dupliquée qui prend un objet objOut
et remplit les propriétés plates en se regardant. Quand une propriété non-plate est trouvée (alias un objet imbriqué) que l'on saute.
// Duplicate object with its flat properties
func duplicate(objOut: Object) -> Object {
// Mirror object type
let objectType: Mirror = Mirror(reflecting: self);
// Iterate on object properties
for child in objectType.children {
// Get label
let label = child.label!
// Handler for flat properties, skip complex objects
switch String(describing: type(of: child.value)) {
case "Double", "Int", "Int64", "String":
objOut.setValue(self.value(forKey: label)!, forKey: label)
break
default:
break
}
}
return objOut
}
dans la classe Manager pour mes Royaumes j'ai la méthode copyFromRealm()
que j'utilise pour créer mes copies d'objets.
Pour vous donner une pratique exemple voici la structure de ma classe de nomination:
Appointment object
- flat properties
- one UpdateInfo object
- flat properties
- one AddressLocation object
- flat properties
- one Address object
- flat properties
- one Coordinates object
- flat properies
- a list of ExtraInfo
- each ExtraInfo object
- flat properties
Voici comment j'ai implémenté la méthode copyFromRealm ():
// Creates copy out of realm
func copyFromRealm() -> Appointment {
// Duplicate base object properties
let cpAppointment = self.duplicate(objOut: Appointment()) as! Appointment
// Duplicate UIU object
cpAppointment.uiu = self.uiu?.duplicate(objOut: UpdateInfo()) as? UpdateInfo
// Duplicate AddressLocation object
let cpAddress = self.addressLocation?.address?.duplicate(objOut: Address()) as? Address
let cpCoordinates = self.addressLocation?.coordinates?.duplicate(objOut: Coordinates()) as? Coordinates
cpAppointment.addressLocation = self.addressLocation?.duplicate(objOut: AddressLocation()) as? AddressLocation
cpAppointment.addressLocation?.address = cpAddress
cpAppointment.addressLocation?.coordinates = cpCoordinates
// Duplicate each ExtraInfo
for other in self.others {
cpAppointment.others.append(other.duplicate(objOut: ExtraInfo()) as! ExtraInfo)
}
return cpAppointment
}
Je n'ai pas pu trouver une bonne et raisonnable façon de travailler avec des objets imbriqués dans ma méthode duplicate (). J'ai pensé à la récursion, mais la complexité du code a trop augmenté.
ce n'est pas optimal mais fonctionne, si je trouve un moyen de gérer aussi objet imbriqué je vais mettre à jour cette réponse.