web-dev-qa-db-ja.com

既存のレルムオブジェクトを簡単に複製/コピーするにはどうすればよいですか?

私はいくつかの関係を持つレルムオブジェクトを持っています、誰もがデータベースに複製を作成するために、コピーメソッドを一般化する良いコードスニペットを持っています。

16
mvo

私の場合、オブジェクトを作成し、永続化したくありませんでした。そのため、segiddinsのソリューションは私には機能しませんでした。

Swift

Swiftでユーザーオブジェクトのクローンを作成するには、次を使用します。

let newUser = User(value: oldUser);

新しいユーザーオブジェクトは永続化されません。

27
Cerlin

主キーがない限り、以下を使用してオブジェクトの浅いコピーを作成できます。

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

同様の問題が発生し、レルムオブジェクトのコピーを取得するための簡単な回避策を見つけました。基本的には、次のように、オブジェクトをNSCopyingプロトコルに準拠させる必要があります。

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

次に、オブジェクトで「copy()」メソッドを呼び出すだけです。

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

       var myCopy = original.copy()
   }
}

コピーを持つことの良いところは、レルム書き込みトランザクションを行わなくてもコピーを変更できることです。ユーザーが一部のデータを編集しているが、まだ保存を押していないか、単に気が変わった場合に便利です。

2
Ahmad

この問題はまだ生きているので、私は解決策を投稿しますが、それでも改善する必要があります。 Object objOutを受け取り、自分自身を見てフラットプロパティを埋める、このメソッドの重複を持つObjectクラスの拡張を作成しました。フラットでないプロパティ(ネストされたオブジェクト)が見つかった場合、そのプロパティはスキップされます。

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

レルムのManagerクラス内には、オブジェクトのコピーを作成するために使用するメソッドcopyFromRealm()があります。実用的な例を示すために、これは私のAppointmentクラスの構造です。

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

これが私が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
}
_

私は、duplicate()メソッド内でネストされたオブジェクトを操作するための適切で合理的な方法を見つけることができませんでした。再帰を考えましたが、コードの複雑さが増しすぎました。

これは最適ではありませんが機能します。ネストされたオブジェクトも管理する方法が見つかった場合は、この回答を更新します。

0
LucioB