简体   繁体   中英

How to save normal array into realm in background thread swift

I have a RealmManager class as bellow:

class RealmManager {

    static func save<T: Object>(obj: [T]) {
        let personRef = ThreadSafeReference(to: obj)
        DispatchQueue.global(qos: .background).async {
            autoreleasepool {
                let realm = try! Realm()
                try! realm.write({
                    realm.add(obj, update: .modified)
                })
            }
        }
    }
}

I'm trying to save a obj array into Realm database but my code do not compile getting this error:

Referencing initializer 'init(to:)' on 'ThreadSafeReference' requires that '[_]' conform to 'ThreadConfined'

Any help?

Code update:

class RealmManager {

    static func save<T: Object>(obj: [T]) {
        let realm = try! Realm()
        realm.asyncSaveArray(obj: obj)
    }

    static func get<T: Object>(type: T.Type) -> [T]? {
        let realm = try! Realm()
        return realm.objects(T.self).toArray(type: T.self)
    }
}

extension Results {
    func toArray<T>(type: T.Type) -> [T] {
        return compactMap { $0 as? T }
    }
}

extension Realm {
    func asyncWrite<T : ThreadConfined>(obj: T, errorHandler: @escaping ((_ error : Swift.Error) -> Void) = { _ in return }, block: @escaping ((Realm, T?) -> Void)) {
        let wrappedObj = ThreadSafeReference(to: obj)
        let config = self.configuration
        DispatchQueue.global(qos: .background).async {
            autoreleasepool {
                do {
                    let realm = try Realm(configuration: config)
                    let obj = realm.resolve(wrappedObj)

                    try realm.write {
                        block(realm, obj)
                    }
                }
                catch {
                    errorHandler(error)
                }
            }
        }
    }

    func asyncSaveArray<T: Object>(obj: [T]) {
        for item in obj {
            self.asyncWrite(obj: item) { (realm, itemToSave) in
                guard let itemToSave = itemToSave else { return }
                realm.add(itemToSave, update: .modified)
            }
        }
    }
}

To pass in an array of objects, you might use a Realm extension:

extension Realm {
  func asyncWrite<T : ThreadConfined>(obj: T, errorHandler: @escaping ((_ error : Swift.Error) -> Void) = { _ in return }, block: @escaping ((Realm, T?) -> Void)) {
    let wrappedObj = ThreadSafeReference(to: obj)
    let config = self.configuration
    DispatchQueue.global(qos: .background).async {
      autoreleasepool {
        do {
          let realm = try Realm(configuration: config)
          let obj = realm.resolve(wrappedObj)
           
          try realm.write {
            block(realm, obj)
          }
        }
        catch {
          errorHandler(error)
        }
      }
    }
  }
   
  func asyncSaveArray<T: Object>(obj: [T]) {
     
    for item in obj {
      self.asyncWrite(obj: item) { (realm, itemToSave) in
        guard itemToSave != nil else { return }
        realm.add(itemToSave!, update: .modified)
      }
    }
  }
}

There might be two possible use cases.

  1. One is to actually pass an array of Object s:
realm.asyncSaveArray(obj: yourObjectsArray)
  1. The other one is instead of passing in the array of objects, you can use an instance of Results<Object> received somewhere in code previously:
var yourObjects = realm.objects(YourType.self)

self.asyncWrite(obj: yourObjects) { (realm, itemToSave) in
        guard itemToSave != nil else { return }
        realm.add(itemToSave!, update: .modified)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM