Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 439 Vote(s) - 3.51 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How can I easily duplicate/copy an existing realm object

#1
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.
Reply

#2
Swift 5+

Creates a Realm managed copy of an existing Realm managed object with ID

extension RLMObject {

func createManagedCopy(withID newID: String) -> RLMObject? {

let realmClass = type(of: self)
guard let realm = self.realm, let primaryKey = realmClass.primaryKey() else {
return nil
}

let shallowCopy = realmClass.init(value: self)
shallowCopy.setValue(newID, forKey: primaryKey)

do {
realm.beginWriteTransaction()
realm.add(shallowCopy)
try realm.commitWriteTransaction()
} catch {
return nil
}

return shallowCopy

}

}
Reply

#3
As of now, Dec 2020, there is no proper solution for 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"
}
```
2. 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
}
}
}
```

3. 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.
Reply

#4
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.
Reply

#5
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.
Reply

#6
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.
Reply

#7
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)
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through