How can I easily duplicate/copy an existing realm object

雨燕双飞 提交于 2021-01-13 06:07:29

问题


I have a Realm Object which has several relationships, anyone has a good code snippet that generalizes a copy method, to create a duplicate in the database.


回答1:


In my case i just wanted to create an object and not persist it. so segiddins's solution didn't work for me.

Swift 3

To create a clone of user object in swift just use

let newUser = User(value: oldUser);

The new user object is not persisted.




回答2:


You can use the following to create a shallow copy of your object, as long as it does not have a primary key:

realm.create(ObjectType.self, withValue: existingObject)



回答3:


I had a similar issue and found a simple workaround to get a copy of a realm object. Basically you just need to make the object conform to the NSCopying protocol, something like:

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
}
}

then you just call the "copy()" method on the object:

class ViewController: UIViewController {
   var original = Original()
   override func viewDidLoad() {
       super.viewDidLoad()

       var myCopy = original.copy()
   }
}

The nice thing about having a copy is that I can modify it without having to be in a realm write transaction. Useful when users are editing some data but didn't hit save yet or simply changed their mind.




回答4:


Since this problem is still alive I post my solution which works but still needs to be improved. I've created an extension of Object class that has this method duplicate that takes an object objOut and fills the flat properties by looking at self. When a non-flat property is found (aka a nested object) that one is skipped.

// 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
}

Inside the Manager class for my Realms I have the method copyFromRealm() that I use to create my copies of objects. To give you a practical example this is the structure of my Appointment class:

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

This is how I've implemented the copyFromRealm() method:

// 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
}

I wasn't able to find out a good and reasonable way to work with nested objects inside my duplicate() method. I thought of recursion but code complexity raised too much.

This is not optimal but works, if I'll find a way to manage also nested object I'll update this answer.




回答5:


As of now, Dec 2020, there is not proper solution of this issue. We have many workarounds though.

Here is the one I have been using, and one with less limitations in my opinion.

  1. Make your Realm Model Object classes conform to codable
class Dog: Object, Codable{
    @objc dynamic var breed:String = "JustAnyDog"
}
  1. Create this helper class
class RealmHelper {
    //Used to expose generic 
    static func DetachedCopy<T:Codable>(of object:T) -> T?{
       do{
           let json = try JSONEncoder().encode(object)
           return try JSONDecoder().decode(T.self, from: json)
       }
       catch let error{
           print(error)
           return nil
       }
    }
}
  1. Call this method whenever you need detached / true deep copy of your Realm Object, like this:
 //Suppose your Realm managed object: let dog:Dog = RealmDBService.shared.getFirstDog()
 guard let detachedDog = RealmHelper.DetachedCopy(of: dog) else{
    print("Could not detach Dog")
    return
 }
//Change/mutate object properties as you want
 detachedDog.breed = "rottweiler"

As you can see we are piggy backing on Swift's JSONEncoder and JSONDecoder, using power of Codable, making true deep copy no matter how many nested objects are there under our realm object. Just make sure all your Realm Model Classes conform to Codable.

Though its NOT an ideal solution, but its one of the most effective workaround.



来源:https://stackoverflow.com/questions/30144657/how-can-i-easily-duplicate-copy-an-existing-realm-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!